smaug: Update fastboot flash bootloader
Updates to flashing bootloader image:
1. Change the name to bootloader since a lot of scripts expect name
bootloader instead of firmware
2. Only update RO,RW-A and RW-B sections on flash. All other sections
remain as is.
BUG=chrome-os-partner:41300
BRANCH=None
TEST=Compiles successfully and fastboot flash bootloader does not
erase VPD data.
Change-Id: Iee37e1720f6568bc5fb1cf39bfe0519ea8c19584
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/276605
Tested-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
diff --git a/src/board/smaug/fastboot.c b/src/board/smaug/fastboot.c
index 8bd4f66..2f8b371 100644
--- a/src/board/smaug/fastboot.c
+++ b/src/board/smaug/fastboot.c
@@ -28,6 +28,7 @@
#include "boot/android_dt.h"
#include "config.h"
#include "drivers/bus/usb/usb.h"
+#include "image/fmap.h"
#include "vboot/firmware_id.h"
struct bdev_info fb_bdev_list[BDEV_COUNT] = {
@@ -61,7 +62,21 @@
PART_NONGPT("chromeos", NULL, BDEV_ENTRY(MMC_BDEV), 0, 0),
PART_NONGPT("mbr", NULL, BDEV_ENTRY(MMC_BDEV), 0, 1),
PART_NONGPT("gpt", NULL, BDEV_ENTRY(MMC_BDEV), 1, 33),
- PART_NONGPT("firmware", NULL, BDEV_ENTRY(FLASH_BDEV), 0, 0),
+ PART_NONGPT("RO_SECTION", NULL, BDEV_ENTRY(FLASH_BDEV), 0, 0),
+ PART_NONGPT("RW_SECTION_A", NULL, BDEV_ENTRY(FLASH_BDEV), 0, 0),
+ PART_NONGPT("RW_SECTION_B", NULL, BDEV_ENTRY(FLASH_BDEV), 0, 0),
+ /*
+ * "bootloader" is a special alias used to flash different firmware
+ * partitions to spi flash. When asked by the host, we report entire spi
+ * flash as the size of this partition. When host asks the device to
+ * flash an image to bootloader partition, device will extract specific
+ * parts from the image i.e. ro, rw-a, rw-b and write them to
+ * appropriate offsets on the spi flash.
+ * This partition name is required to satisfy host-side scripts that
+ * want to update ro, rw-a and rw-b sections of the firmware using a
+ * single name and image.
+ */
+ PART_NONGPT("bootloader", NULL, BDEV_ENTRY(FLASH_BDEV), 0, 9),
};
size_t fb_part_count = ARRAY_SIZE(fb_part_list);
@@ -111,9 +126,40 @@
for (i = 0; i < BDEV_COUNT; i++)
fb_fill_bdev_list(i, bdev_ctrlr_arr[i]);
- fb_fill_part_list("firmware", 0, lib_sysinfo.spi_flash.size /
- lib_sysinfo.spi_flash.sector_size);
fb_fill_part_list("chromeos", 0, backend_get_bdev_size_blocks("mmc"));
+
+ FmapArea area;
+ const char *name;
+ size_t flash_sec_size = lib_sysinfo.spi_flash.sector_size;
+
+ for (i = 0; i < fb_part_count; i++) {
+ if (fb_part_list[i].bdev_info != BDEV_ENTRY(FLASH_BDEV))
+ continue;
+
+ name = fb_part_list[i].part_name;
+
+ if (fmap_find_area(name, &area)) {
+ /*
+ * Special partition bootloader cannot be found on the
+ * spi flash using fmap_find_area. Check if current
+ * flash_bdec partition is bootloader and set its range
+ * as the entire spi flash.
+ */
+ if (!strcmp(name, "bootloader"))
+ fb_fill_part_list("bootloader", 0,
+ lib_sysinfo.spi_flash.size /
+ flash_sec_size);
+ else
+ printf("ERROR: Area %s not found\n", name);
+ continue;
+ }
+
+ assert(ALIGN(area.offset, flash_sec_size) == area.offset);
+ assert(ALIGN(area.size, flash_sec_size) == area.size);
+
+ fb_fill_part_list(name, area.offset / flash_sec_size,
+ area.size / flash_sec_size);
+ }
}
int board_user_confirmation(void)
@@ -134,3 +180,56 @@
}
return ret;
}
+
+/*
+ * This routine is used to handle fastboot calls to write image to special
+ * "bootloader" partition. It is assumed that this call is made before fastboot
+ * protocol handler calls backend write partition handler.
+ * This routine takes an image equal to the size of the spi flash and extracts
+ * partitions that need to flashed i.e. ro, rw-a and rw-b.
+ */
+backend_ret_t board_write_partition(const char *name, void *image_addr,
+ size_t image_size)
+{
+ /* Handle writes to bootloader partition. Others use default path. */
+ if (strcmp(name, "bootloader"))
+ return BE_NOT_HANDLED;
+
+ /* Cannot handle sparse image here. */
+ if (is_sparse_image(image_addr))
+ return BE_WRITE_ERR;
+
+ static const char * const part_names[] = {
+ "RO_SECTION",
+ "RW_SECTION_A",
+ "RW_SECTION_B",
+ };
+
+ int i;
+ struct part_info *part;
+ uintptr_t offset;
+ size_t size;
+ size_t flash_size = lib_sysinfo.spi_flash.size;
+ size_t flash_sec_size = lib_sysinfo.spi_flash.sector_size;
+
+ for (i = 0; i < ARRAY_SIZE(part_names); i++) {
+
+ part = get_part_info(part_names[i]);
+
+ /* Ensure image size is equal to flash size. */
+ if (flash_size != image_size)
+ return BE_IMAGE_OVERFLOW_ERR;
+
+ /*
+ * We only write to specific regions in spi flash. Calculate the
+ * offset within the image to write to ro, rw-a and rw-b
+ * sections.
+ */
+ offset = (uintptr_t)image_addr + part->base * flash_sec_size;
+ size = part->size * flash_sec_size;
+
+ backend_write_partition(part_names[i], (void *)offset, size);
+ }
+
+ return BE_SUCCESS;
+}