|
|
|
@ -13,6 +13,8 @@ |
|
|
|
|
#include <part.h> |
|
|
|
|
#include <mmc.h> |
|
|
|
|
#include <div64.h> |
|
|
|
|
#include <linux/compat.h> |
|
|
|
|
#include <android_image.h> |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* FIXME: Ensure we always set these names via Kconfig once xxx_PARTITION is |
|
|
|
@ -27,6 +29,8 @@ |
|
|
|
|
#define CONFIG_FASTBOOT_MBR_NAME "mbr" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#define BOOT_PARTITION_NAME "boot" |
|
|
|
|
|
|
|
|
|
struct fb_mmc_sparse { |
|
|
|
|
struct blk_desc *dev_desc; |
|
|
|
|
}; |
|
|
|
@ -99,6 +103,163 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info, |
|
|
|
|
fastboot_okay(""); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ANDROID_BOOT_IMAGE |
|
|
|
|
/**
|
|
|
|
|
* Read Android boot image header from boot partition. |
|
|
|
|
* |
|
|
|
|
* @param[in] dev_desc MMC device descriptor |
|
|
|
|
* @param[in] info Boot partition info |
|
|
|
|
* @param[out] hdr Where to store read boot image header |
|
|
|
|
* |
|
|
|
|
* @return Boot image header sectors count or 0 on error |
|
|
|
|
*/ |
|
|
|
|
static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc, |
|
|
|
|
disk_partition_t *info, |
|
|
|
|
struct andr_img_hdr *hdr) |
|
|
|
|
{ |
|
|
|
|
ulong sector_size; /* boot partition sector size */ |
|
|
|
|
lbaint_t hdr_sectors; /* boot image header sectors count */ |
|
|
|
|
int res; |
|
|
|
|
|
|
|
|
|
/* Calculate boot image sectors count */ |
|
|
|
|
sector_size = info->blksz; |
|
|
|
|
hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size); |
|
|
|
|
if (hdr_sectors == 0) { |
|
|
|
|
error("invalid number of boot sectors: 0"); |
|
|
|
|
fastboot_fail("invalid number of boot sectors: 0"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Read the boot image header */ |
|
|
|
|
res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr); |
|
|
|
|
if (res == 0) { |
|
|
|
|
error("cannot read header from boot partition"); |
|
|
|
|
fastboot_fail("cannot read header from boot partition"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Check boot header magic string */ |
|
|
|
|
res = android_image_check_header(hdr); |
|
|
|
|
if (res != 0) { |
|
|
|
|
error("bad boot image magic"); |
|
|
|
|
fastboot_fail("boot partition not initialized"); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return hdr_sectors; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Write downloaded zImage to boot partition and repack it properly. |
|
|
|
|
* |
|
|
|
|
* @param dev_desc MMC device descriptor |
|
|
|
|
* @param download_buffer Address to fastboot buffer with zImage in it |
|
|
|
|
* @param download_bytes Size of fastboot buffer, in bytes |
|
|
|
|
* |
|
|
|
|
* @return 0 on success or -1 on error |
|
|
|
|
*/ |
|
|
|
|
static int fb_mmc_update_zimage(struct blk_desc *dev_desc, |
|
|
|
|
void *download_buffer, |
|
|
|
|
unsigned int download_bytes) |
|
|
|
|
{ |
|
|
|
|
u32 hdr_addr; /* boot image header address */ |
|
|
|
|
struct andr_img_hdr *hdr; /* boot image header */ |
|
|
|
|
lbaint_t hdr_sectors; /* boot image header sectors */ |
|
|
|
|
u8 *ramdisk_buffer; |
|
|
|
|
u32 ramdisk_sector_start; |
|
|
|
|
u32 ramdisk_sectors; |
|
|
|
|
u32 kernel_sector_start; |
|
|
|
|
u32 kernel_sectors; |
|
|
|
|
u32 sectors_per_page; |
|
|
|
|
disk_partition_t info; |
|
|
|
|
int res; |
|
|
|
|
|
|
|
|
|
puts("Flashing zImage\n"); |
|
|
|
|
|
|
|
|
|
/* Get boot partition info */ |
|
|
|
|
res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info); |
|
|
|
|
if (res < 0) { |
|
|
|
|
error("cannot find boot partition"); |
|
|
|
|
fastboot_fail("cannot find boot partition"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Put boot image header in fastboot buffer after downloaded zImage */ |
|
|
|
|
hdr_addr = (u32)download_buffer + ALIGN(download_bytes, PAGE_SIZE); |
|
|
|
|
hdr = (struct andr_img_hdr *)hdr_addr; |
|
|
|
|
|
|
|
|
|
/* Read boot image header */ |
|
|
|
|
hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr); |
|
|
|
|
if (hdr_sectors == 0) { |
|
|
|
|
error("unable to read boot image header"); |
|
|
|
|
fastboot_fail("unable to read boot image header"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Check if boot image has second stage in it (we don't support it) */ |
|
|
|
|
if (hdr->second_size > 0) { |
|
|
|
|
error("moving second stage is not supported yet"); |
|
|
|
|
fastboot_fail("moving second stage is not supported yet"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Extract ramdisk location */ |
|
|
|
|
sectors_per_page = hdr->page_size / info.blksz; |
|
|
|
|
ramdisk_sector_start = info.start + sectors_per_page; |
|
|
|
|
ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * |
|
|
|
|
sectors_per_page; |
|
|
|
|
ramdisk_sectors = DIV_ROUND_UP(hdr->ramdisk_size, hdr->page_size) * |
|
|
|
|
sectors_per_page; |
|
|
|
|
|
|
|
|
|
/* Read ramdisk and put it in fastboot buffer after boot image header */ |
|
|
|
|
ramdisk_buffer = (u8 *)hdr + (hdr_sectors * info.blksz); |
|
|
|
|
res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors, |
|
|
|
|
ramdisk_buffer); |
|
|
|
|
if (res == 0) { |
|
|
|
|
error("cannot read ramdisk from boot partition"); |
|
|
|
|
fastboot_fail("cannot read ramdisk from boot partition"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Write new kernel size to boot image header */ |
|
|
|
|
hdr->kernel_size = download_bytes; |
|
|
|
|
res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr); |
|
|
|
|
if (res == 0) { |
|
|
|
|
error("cannot writeback boot image header"); |
|
|
|
|
fastboot_fail("cannot write back boot image header"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Write the new downloaded kernel */ |
|
|
|
|
kernel_sector_start = info.start + sectors_per_page; |
|
|
|
|
kernel_sectors = DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * |
|
|
|
|
sectors_per_page; |
|
|
|
|
res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors, |
|
|
|
|
download_buffer); |
|
|
|
|
if (res == 0) { |
|
|
|
|
error("cannot write new kernel"); |
|
|
|
|
fastboot_fail("cannot write new kernel"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Write the saved ramdisk back */ |
|
|
|
|
ramdisk_sector_start = info.start + sectors_per_page; |
|
|
|
|
ramdisk_sector_start += DIV_ROUND_UP(hdr->kernel_size, hdr->page_size) * |
|
|
|
|
sectors_per_page; |
|
|
|
|
res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors, |
|
|
|
|
ramdisk_buffer); |
|
|
|
|
if (res == 0) { |
|
|
|
|
error("cannot write back original ramdisk"); |
|
|
|
|
fastboot_fail("cannot write back original ramdisk"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
puts("........ zImage was updated in boot partition\n"); |
|
|
|
|
fastboot_okay(""); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
void fb_mmc_flash_write(const char *cmd, void *download_buffer, |
|
|
|
|
unsigned int download_bytes) |
|
|
|
|
{ |
|
|
|
@ -153,6 +314,13 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer, |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ANDROID_BOOT_IMAGE |
|
|
|
|
if (strncasecmp(cmd, "zimage", 6) == 0) { |
|
|
|
|
fb_mmc_update_zimage(dev_desc, download_buffer, download_bytes); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) { |
|
|
|
|
error("cannot find partition: '%s'\n", cmd); |
|
|
|
|
fastboot_fail("cannot find partition"); |
|
|
|
|