Commit efeccfe7f3b3d45f9a94f4eb62f4548b1a2fbfb5
Committed by
Lukasz Majewski
1 parent
e5f00f0180
Exists in
smarc_8mq_lf_v2020.04
and in
18 other branches
fastboot: Add support for flashing zImage
This patch adds support for flashing zImage to the Android boot partition on eMMC. Usage: $ fastboot flash zImage <path_to_zImage> It's based on [1]. [1] http://omapzoom.org/?p=repo/u-boot.git;a=commit;h=3393b908c1e848bba3706612cbe50aa8970720b3 Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
Showing 1 changed file with 168 additions and 0 deletions Side-by-side Diff
common/fb_mmc.c
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | #include <part.h> |
14 | 14 | #include <mmc.h> |
15 | 15 | #include <div64.h> |
16 | +#include <linux/compat.h> | |
17 | +#include <android_image.h> | |
16 | 18 | |
17 | 19 | /* |
18 | 20 | * FIXME: Ensure we always set these names via Kconfig once xxx_PARTITION is |
... | ... | @@ -27,6 +29,8 @@ |
27 | 29 | #define CONFIG_FASTBOOT_MBR_NAME "mbr" |
28 | 30 | #endif |
29 | 31 | |
32 | +#define BOOT_PARTITION_NAME "boot" | |
33 | + | |
30 | 34 | struct fb_mmc_sparse { |
31 | 35 | struct blk_desc *dev_desc; |
32 | 36 | }; |
... | ... | @@ -99,6 +103,163 @@ |
99 | 103 | fastboot_okay(""); |
100 | 104 | } |
101 | 105 | |
106 | +#ifdef CONFIG_ANDROID_BOOT_IMAGE | |
107 | +/** | |
108 | + * Read Android boot image header from boot partition. | |
109 | + * | |
110 | + * @param[in] dev_desc MMC device descriptor | |
111 | + * @param[in] info Boot partition info | |
112 | + * @param[out] hdr Where to store read boot image header | |
113 | + * | |
114 | + * @return Boot image header sectors count or 0 on error | |
115 | + */ | |
116 | +static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc, | |
117 | + disk_partition_t *info, | |
118 | + struct andr_img_hdr *hdr) | |
119 | +{ | |
120 | + ulong sector_size; /* boot partition sector size */ | |
121 | + lbaint_t hdr_sectors; /* boot image header sectors count */ | |
122 | + int res; | |
123 | + | |
124 | + /* Calculate boot image sectors count */ | |
125 | + sector_size = info->blksz; | |
126 | + hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size); | |
127 | + if (hdr_sectors == 0) { | |
128 | + error("invalid number of boot sectors: 0"); | |
129 | + fastboot_fail("invalid number of boot sectors: 0"); | |
130 | + return 0; | |
131 | + } | |
132 | + | |
133 | + /* Read the boot image header */ | |
134 | + res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr); | |
135 | + if (res == 0) { | |
136 | + error("cannot read header from boot partition"); | |
137 | + fastboot_fail("cannot read header from boot partition"); | |
138 | + return 0; | |
139 | + } | |
140 | + | |
141 | + /* Check boot header magic string */ | |
142 | + res = android_image_check_header(hdr); | |
143 | + if (res != 0) { | |
144 | + error("bad boot image magic"); | |
145 | + fastboot_fail("boot partition not initialized"); | |
146 | + return 0; | |
147 | + } | |
148 | + | |
149 | + return hdr_sectors; | |
150 | +} | |
151 | + | |
152 | +/** | |
153 | + * Write downloaded zImage to boot partition and repack it properly. | |
154 | + * | |
155 | + * @param dev_desc MMC device descriptor | |
156 | + * @param download_buffer Address to fastboot buffer with zImage in it | |
157 | + * @param download_bytes Size of fastboot buffer, in bytes | |
158 | + * | |
159 | + * @return 0 on success or -1 on error | |
160 | + */ | |
161 | +static int fb_mmc_update_zimage(struct blk_desc *dev_desc, | |
162 | + void *download_buffer, | |
163 | + unsigned int download_bytes) | |
164 | +{ | |
165 | + u32 hdr_addr; /* boot image header address */ | |
166 | + struct andr_img_hdr *hdr; /* boot image header */ | |
167 | + lbaint_t hdr_sectors; /* boot image header sectors */ | |
168 | + u8 *ramdisk_buffer; | |
169 | + u32 ramdisk_sector_start; | |
170 | + u32 ramdisk_sectors; | |
171 | + u32 kernel_sector_start; | |
172 | + u32 kernel_sectors; | |
173 | + u32 sectors_per_page; | |
174 | + disk_partition_t info; | |
175 | + int res; | |
176 | + | |
177 | + puts("Flashing zImage\n"); | |
178 | + | |
179 | + /* Get boot partition info */ | |
180 | + res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info); | |
181 | + if (res < 0) { | |
182 | + error("cannot find boot partition"); | |
183 | + fastboot_fail("cannot find boot partition"); | |
184 | + return -1; | |
185 | + } | |
186 | + | |
187 | + /* Put boot image header in fastboot buffer after downloaded zImage */ | |
188 | + hdr_addr = (u32)download_buffer + ALIGN(download_bytes, PAGE_SIZE); | |
189 | + hdr = (struct andr_img_hdr *)hdr_addr; | |
190 | + | |
191 | + /* Read boot image header */ | |
192 | + hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr); | |
193 | + if (hdr_sectors == 0) { | |
194 | + error("unable to read boot image header"); | |
195 | + fastboot_fail("unable to read boot image header"); | |
196 | + return -1; | |
197 | + } | |
198 | + | |
199 | + /* Check if boot image has second stage in it (we don't support it) */ | |
200 | + if (hdr->second_size > 0) { | |
201 | + error("moving second stage is not supported yet"); | |
202 | + fastboot_fail("moving second stage is not supported yet"); | |
203 | + return -1; | |
204 | + } | |
205 | + | |
206 | + /* Extract ramdisk location */ | |
207 | + sectors_per_page = hdr->page_size / info.blksz; | |
208 | + ramdisk_sector_start = info.start + sectors_per_page; | |
209 | + ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * | |
210 | + sectors_per_page; | |
211 | + ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) * | |
212 | + sectors_per_page; | |
213 | + | |
214 | + /* Read ramdisk and put it in fastboot buffer after boot image header */ | |
215 | + ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz); | |
216 | + res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors, | |
217 | + ramdisk_buffer); | |
218 | + if (res == 0) { | |
219 | + error("cannot read ramdisk from boot partition"); | |
220 | + fastboot_fail("cannot read ramdisk from boot partition"); | |
221 | + return -1; | |
222 | + } | |
223 | + | |
224 | + /* Write new kernel size to boot image header */ | |
225 | + hdr->kernel_size = download_bytes; | |
226 | + res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr); | |
227 | + if (res == 0) { | |
228 | + error("cannot writeback boot image header"); | |
229 | + fastboot_fail("cannot write back boot image header"); | |
230 | + return -1; | |
231 | + } | |
232 | + | |
233 | + /* Write the new downloaded kernel */ | |
234 | + kernel_sector_start = info.start + sectors_per_page; | |
235 | + kernel_sectors = DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * | |
236 | + sectors_per_page; | |
237 | + res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors, | |
238 | + download_buffer); | |
239 | + if (res == 0) { | |
240 | + error("cannot write new kernel"); | |
241 | + fastboot_fail("cannot write new kernel"); | |
242 | + return -1; | |
243 | + } | |
244 | + | |
245 | + /* Write the saved ramdisk back */ | |
246 | + ramdisk_sector_start = info.start + sectors_per_page; | |
247 | + ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * | |
248 | + sectors_per_page; | |
249 | + res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors, | |
250 | + ramdisk_buffer); | |
251 | + if (res == 0) { | |
252 | + error("cannot write back original ramdisk"); | |
253 | + fastboot_fail("cannot write back original ramdisk"); | |
254 | + return -1; | |
255 | + } | |
256 | + | |
257 | + puts("........ zImage was updated in boot partition\n"); | |
258 | + fastboot_okay(""); | |
259 | + return 0; | |
260 | +} | |
261 | +#endif | |
262 | + | |
102 | 263 | void fb_mmc_flash_write(const char *cmd, void *download_buffer, |
103 | 264 | unsigned int download_bytes) |
104 | 265 | { |
... | ... | @@ -149,6 +310,13 @@ |
149 | 310 | } |
150 | 311 | printf("........ success\n"); |
151 | 312 | fastboot_okay(""); |
313 | + return; | |
314 | + } | |
315 | +#endif | |
316 | + | |
317 | +#ifdef CONFIG_ANDROID_BOOT_IMAGE | |
318 | + if (strncasecmp(cmd, "zimage", 6) == 0) { | |
319 | + fb_mmc_update_zimage(dev_desc, download_buffer, download_bytes); | |
152 | 320 | return; |
153 | 321 | } |
154 | 322 | #endif |