blob: 2f8b371a2abd37c61a8f24e2ee93bdad6da07d42 [file] [log] [blame]
/*
* Copyright 2015 Google Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <libpayload.h>
#include <udc/chipidea.h>
#include "board/smaug/fastboot.h"
#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] = {
[MMC_BDEV] = {"mmc", NULL, NULL},
[FLASH_BDEV] = {"flash", NULL, NULL},
};
size_t fb_bdev_count = ARRAY_SIZE(fb_bdev_list);
struct part_info fb_part_list[] = {
PART_GPT("boot", "ext4", BDEV_ENTRY(MMC_BDEV),
GPT_TYPE(CHROMEOS_KERNEL), 0),
PART_GPT("kernel-a", "ext4", BDEV_ENTRY(MMC_BDEV),
GPT_TYPE(CHROMEOS_KERNEL), 0),
PART_GPT("kernel-b", "ext4", BDEV_ENTRY(MMC_BDEV),
GPT_TYPE(CHROMEOS_KERNEL), 1),
PART_GPT("recovery", "ext4", BDEV_ENTRY(MMC_BDEV),
GPT_TYPE(CHROMEOS_KERNEL), 2),
PART_GPT("kernel", "ext4", BDEV_ENTRY(MMC_BDEV),
GPT_TYPE(CHROMEOS_KERNEL), 0),
PART_GPT("system", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 0),
PART_GPT("vendor", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 1),
PART_GPT("cache", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 2),
PART_GPT("data", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 3),
PART_GPT("metadata", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS),
4),
PART_GPT("boot", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 5),
PART_GPT("misc", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS), 6),
PART_GPT("persistent", "ext4", BDEV_ENTRY(MMC_BDEV), GPT_TYPE(LINUX_FS),
7),
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("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);
int get_board_var(struct fb_cmd *cmd, fb_getvar_t var)
{
int ret = 0;
struct fb_buffer *output = &cmd->output;
switch(var) {
case FB_BOOTLOADER_VERSION: {
const char *version = get_active_fw_id();
if (version == NULL)
ret = -1;
else
fb_add_string(output, "%s", version);
break;
}
case FB_PRODUCT:
fb_add_string(output, "%s", hardware_name());
break;
case FB_BASEBAND_VERSION:
fb_add_string(output, "%s", "N/A");
break;
default:
ret = -1;
break;
}
return ret;
}
int board_should_enter_device_mode(void)
{
return 1;
}
void fastboot_chipset_init(struct usbdev_ctrl **udc, device_descriptor_t *dd)
{
dc_usb_initialize();
*udc = chipidea_init(dd);
}
void fill_fb_info(BlockDevCtrlr *bdev_ctrlr_arr[BDEV_COUNT])
{
int i;
for (i = 0; i < BDEV_COUNT; i++)
fb_fill_bdev_list(i, bdev_ctrlr_arr[i]);
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)
{
int ret = 0;
while (1) {
uint32_t ch = getchar();
if (ch == '\r') {
ret = 1;
break;
}
if (ch == ' ') {
ret = 0;
break;
}
}
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;
}