]> git.sur5r.net Git - u-boot/blob - common/fb_mmc.c
fastboot: Move fastboot response functions to fastboot core
[u-boot] / common / fb_mmc.c
1 /*
2  * Copyright 2014 Broadcom Corporation.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <config.h>
8 #include <common.h>
9 #include <fastboot.h>
10 #include <fb_mmc.h>
11 #include <part.h>
12 #include <aboot.h>
13 #include <sparse_format.h>
14 #include <mmc.h>
15
16 #ifndef CONFIG_FASTBOOT_GPT_NAME
17 #define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME
18 #endif
19
20 static char *response_str;
21
22 static int get_partition_info_efi_by_name_or_alias(block_dev_desc_t *dev_desc,
23                 const char *name, disk_partition_t *info)
24 {
25         int ret;
26
27         ret = get_partition_info_efi_by_name(dev_desc, name, info);
28         if (ret) {
29                 /* strlen("fastboot_partition_alias_") + 32(part_name) + 1 */
30                 char env_alias_name[25 + 32 + 1];
31                 char *aliased_part_name;
32
33                 /* check for alias */
34                 strcpy(env_alias_name, "fastboot_partition_alias_");
35                 strncat(env_alias_name, name, 32);
36                 aliased_part_name = getenv(env_alias_name);
37                 if (aliased_part_name != NULL)
38                         ret = get_partition_info_efi_by_name(dev_desc,
39                                         aliased_part_name, info);
40         }
41         return ret;
42 }
43
44 static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info,
45                 const char *part_name, void *buffer,
46                 unsigned int download_bytes)
47 {
48         lbaint_t blkcnt;
49         lbaint_t blks;
50
51         /* determine number of blocks to write */
52         blkcnt = ((download_bytes + (info->blksz - 1)) & ~(info->blksz - 1));
53         blkcnt = blkcnt / info->blksz;
54
55         if (blkcnt > info->size) {
56                 error("too large for partition: '%s'\n", part_name);
57                 fastboot_fail(response_str, "too large for partition");
58                 return;
59         }
60
61         puts("Flashing Raw Image\n");
62
63         blks = dev_desc->block_write(dev_desc->dev, info->start, blkcnt,
64                                      buffer);
65         if (blks != blkcnt) {
66                 error("failed writing to device %d\n", dev_desc->dev);
67                 fastboot_fail(response_str, "failed writing to device");
68                 return;
69         }
70
71         printf("........ wrote " LBAFU " bytes to '%s'\n", blkcnt * info->blksz,
72                part_name);
73         fastboot_okay(response_str, "");
74 }
75
76 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
77                         unsigned int download_bytes, char *response)
78 {
79         block_dev_desc_t *dev_desc;
80         disk_partition_t info;
81
82         /* initialize the response buffer */
83         response_str = response;
84
85         dev_desc = get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
86         if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
87                 error("invalid mmc device\n");
88                 fastboot_fail(response_str, "invalid mmc device");
89                 return;
90         }
91
92         if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
93                 printf("%s: updating MBR, Primary and Backup GPT(s)\n",
94                        __func__);
95                 if (is_valid_gpt_buf(dev_desc, download_buffer)) {
96                         printf("%s: invalid GPT - refusing to write to flash\n",
97                                __func__);
98                         fastboot_fail(response_str, "invalid GPT partition");
99                         return;
100                 }
101                 if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
102                         printf("%s: writing GPT partitions failed\n", __func__);
103                         fastboot_fail(response_str,
104                                       "writing GPT partitions failed");
105                         return;
106                 }
107                 printf("........ success\n");
108                 fastboot_okay(response_str, "");
109                 return;
110         } else if (get_partition_info_efi_by_name_or_alias(dev_desc, cmd, &info)) {
111                 error("cannot find partition: '%s'\n", cmd);
112                 fastboot_fail(response_str, "cannot find partition");
113                 return;
114         }
115
116         if (is_sparse_image(download_buffer))
117                 write_sparse_image(dev_desc, &info, cmd, download_buffer,
118                                    download_bytes);
119         else
120                 write_raw_image(dev_desc, &info, cmd, download_buffer,
121                                 download_bytes);
122
123         fastboot_okay(response_str, "");
124 }
125
126 void fb_mmc_erase(const char *cmd, char *response)
127 {
128         int ret;
129         block_dev_desc_t *dev_desc;
130         disk_partition_t info;
131         lbaint_t blks, blks_start, blks_size, grp_size;
132         struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
133
134         if (mmc == NULL) {
135                 error("invalid mmc device");
136                 fastboot_fail(response_str, "invalid mmc device");
137                 return;
138         }
139
140         /* initialize the response buffer */
141         response_str = response;
142
143         dev_desc = get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
144         if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
145                 error("invalid mmc device");
146                 fastboot_fail(response_str, "invalid mmc device");
147                 return;
148         }
149
150         ret = get_partition_info_efi_by_name_or_alias(dev_desc, cmd, &info);
151         if (ret) {
152                 error("cannot find partition: '%s'", cmd);
153                 fastboot_fail(response_str, "cannot find partition");
154                 return;
155         }
156
157         /* Align blocks to erase group size to avoid erasing other partitions */
158         grp_size = mmc->erase_grp_size;
159         blks_start = (info.start + grp_size - 1) & ~(grp_size - 1);
160         if (info.size >= grp_size)
161                 blks_size = (info.size - (blks_start - info.start)) &
162                                 (~(grp_size - 1));
163         else
164                 blks_size = 0;
165
166         printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
167                blks_start, blks_start + blks_size);
168
169         blks = dev_desc->block_erase(dev_desc->dev, blks_start, blks_size);
170         if (blks != blks_size) {
171                 error("failed erasing from device %d", dev_desc->dev);
172                 fastboot_fail(response_str, "failed erasing from device");
173                 return;
174         }
175
176         printf("........ erased " LBAFU " bytes from '%s'\n",
177                blks_size * info.blksz, cmd);
178         fastboot_okay(response_str, "");
179 }