Chromium Code Reviews| Index: common/cmd_cros_rec.c |
| diff --git a/common/cmd_cros_rec.c b/common/cmd_cros_rec.c |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2b74c58190fa37149120290cf1bea7a637d4c4c2 |
| --- /dev/null |
| +++ b/common/cmd_cros_rec.c |
| @@ -0,0 +1,245 @@ |
| +/* |
| + * Copyright 2010, Google Inc. |
|
Che-Liang Chiou
2011/03/09 02:37:53
2011. I would suggest we use the "Chromium OS Auth
Tom Wai-Hong Tam
2011/03/09 10:15:05
Done.
|
| + * All rights reserved. |
| + * |
| + * Redistribution and use in source and binary forms, with or without |
| + * modification, are permitted provided that the following conditions are |
| + * met: |
| + * |
| + * * Redistributions of source code must retain the above copyright |
| + * notice, this list of conditions and the following disclaimer. |
| + * * Redistributions in binary form must reproduce the above |
| + * copyright notice, this list of conditions and the following disclaimer |
| + * in the documentation and/or other materials provided with the |
| + * distribution. |
| + * * Neither the name of Google Inc. nor the names of its |
| + * contributors may be used to endorse or promote products derived from |
| + * this software without specific prior written permission. |
| + * |
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| + * |
| + * Alternatively, this software may be distributed under the terms of the |
| + * GNU General Public License ("GPL") version 2 as published by the Free |
| + * Software Foundation. |
| + */ |
| + |
| +/* Debug commands for Chrome OS recovery mode firmware */ |
| + |
| +#include <common.h> |
| +#include <command.h> |
| +#include <mmc.h> |
| +#include <usb.h> |
| + |
| +#include <bmpblk_header.h> |
| +#include <chromeos/gbb_bmpblk.h> |
| +#include <chromeos/hardware_interface.h> |
| + |
| +#include <gbb_header.h> |
| +#include <load_firmware_fw.h> |
| +#include <load_kernel_fw.h> |
| +#include <chromeos/boot_device_impl.h> |
| + |
| +#ifdef VBOOT_DEBUG |
| +#define WARN_ON_FAILURE(action) do { \ |
| + int return_code = (action); \ |
| + if (return_code != 0) \ |
| + debug("Boot Stub: %s failed, returning %d\n", \ |
| + #action, return_code); \ |
| +} while (0) |
| +#else |
| +#define WARN_ON_FAILURE(action) action |
| +#endif |
| + |
| +int lcd_clear(); |
|
Che-Liang Chiou
2011/03/09 02:37:53
Where is this function defined? Would you add a co
Tom Wai-Hong Tam
2011/03/09 10:15:05
Fixed it. Now it is included in lcd.h.
|
| + |
| +int g_is_dev = 0; |
|
Che-Liang Chiou
2011/03/09 02:37:53
Why use a global variable, instead of polling the
Tom Wai-Hong Tam
2011/03/09 10:15:05
Checking it once can keep the logic simple and sec
|
| + |
| +static void sleep_ms(int msecond) |
| +{ |
| + const ulong start = get_timer(0); |
| + const ulong delay = msecond * CONFIG_SYS_HZ / 1000; |
| + |
| + while (!ctrlc() && get_timer(start) < delay) |
| + udelay(100); |
| +} |
| + |
| +static int is_mmc_storage_present(void) |
| +{ |
| + return mmc_legacy_init(1) == 0; |
|
Che-Liang Chiou
2011/03/09 06:55:26
Why pass 1? Is this value cross-platform? If not,
Tom Wai-Hong Tam
2011/03/09 10:15:05
There are 2 MMC devices in the system. 0 is the ma
|
| +} |
| + |
| +static int is_usb_storage_present(void) |
| +{ |
| + int i; |
| + usb_stop(); |
|
Che-Liang Chiou
2011/03/09 06:55:26
Do we have to restart usb here? Should add a FIXME
Tom Wai-Hong Tam
2011/03/09 10:15:05
OK. I added a TODO.
|
| + i = usb_init(); |
| +#ifdef CONFIG_USB_STORAGE |
| + if (i >= 0) |
| + return usb_stor_scan(1) == 0; |
|
Che-Liang Chiou
2011/03/09 06:55:26
Same as above. (Why 1?)
Tom Wai-Hong Tam
2011/03/09 10:15:05
Now 1 is the mode that to probe storage device.
|
| +#else |
| + return i; |
| +#endif |
| +} |
| + |
| +static int write_log(void) |
| +{ |
| + /* TODO Implement it when Chrome OS firmware logging is ready. */ |
| + return 0; |
| +} |
| + |
| +static int clear_ram_not_in_use(void) |
| +{ |
| + /* TODO Implement it when the memory layout is defined. */ |
| + return 0; |
| +} |
| + |
| +int load_kernel(uint8_t *load_addr, size_t load_size) |
|
Che-Liang Chiou
2011/03/09 06:55:26
Normal firmware also needs to call LoadKernel(). I
Tom Wai-Hong Tam
2011/03/09 10:15:05
Will change it when your CL is committed.
|
| +{ |
| + LoadKernelParams par; |
| + block_dev_desc_t *dev_desc; |
| + VbNvContext vnc; |
| + int i, status; |
| + GoogleBinaryBlockHeader *gbbh = (void *)(TEXT_BASE + CONFIG_OFFSET_GBB); |
|
Che-Liang Chiou
2011/03/09 02:37:53
This address might not be valid. Please use the in
Tom Wai-Hong Tam
2011/03/09 10:15:05
Done.
|
| + char buffer[CONFIG_SYS_CBSIZE]; |
| + |
| + if ((dev_desc = get_bootdev()) == NULL) { |
| + printf("No boot device set yet\n"); |
| + return 1; |
| + } |
| + |
| + par.header_sign_key_blob = (uint8_t*)gbbh + gbbh->recovery_key_offset; |
| + par.bytes_per_lba = (uint64_t) dev_desc->blksz; |
| + par.ending_lba = (uint64_t) get_limit() - 1; |
| + par.kernel_buffer = load_addr; |
| + par.kernel_buffer_size = load_size; |
| + par.boot_flags = BOOT_FLAG_RECOVERY | BOOT_FLAG_SKIP_ADDR_CHECK; |
| + /* TODO: load vnc.raw from NV storage */ |
| + par.nv_context = &vnc; |
| + |
| + if (g_is_dev) { |
| + par.boot_flags |= BOOT_FLAG_DEVELOPER; |
| + } |
| + |
| + status = LoadKernel(&par); |
| + |
| + if (vnc.raw_changed) { |
| + /* TODO: save vnc.raw to NV storage */ |
| + } |
| + |
| + switch (status) { |
| + case LOAD_KERNEL_SUCCESS: |
| + puts("Success; good kernel found on device\n"); |
| + printf("partition_number: %lld\n", |
| + par.partition_number); |
| + printf("bootloader_address: 0x%llx", |
| + par.bootloader_address); |
| + printf("bootloader_size: 0x%llx", par.bootloader_size); |
| + puts("partition_guid:"); |
| + for (i = 0; i < 16; i++) |
| + printf(" %02x", par.partition_guid[i]); |
| + putc('\n'); |
| + |
| + lcd_clear(); |
| + |
| + strcpy(buffer, "console=ttyS0,115200n8 "); |
| + strcat(buffer, getenv("platform_extras")); |
| + setenv("bootargs", buffer); |
| + sprintf(buffer, "%lld", par.partition_number + 1); |
| + setenv("rootpart", buffer); |
| + |
| + source(CONFIG_LOADADDR + par.bootloader_address - |
| + 0x100000, NULL); |
| + run_command("bootm ${loadaddr}", 0); |
| + break; |
| + case LOAD_KERNEL_NOT_FOUND: |
| + puts("No kernel found on device\n"); |
| + break; |
| + case LOAD_KERNEL_INVALID: |
| + puts("Only invalid kernels found on device\n"); |
| + break; |
| + case LOAD_KERNEL_RECOVERY: |
| + puts("Internal error; reboot to recovery mode\n"); |
| + break; |
| + case LOAD_KERNEL_REBOOT: |
| + puts("Internal error; reboot to current mode\n"); |
| + break; |
| + default: |
| + printf("Unexpected return status from LoadKernel: %d\n", |
| + status); |
| + return 1; |
| + } |
| + return 0; |
| +} |
| + |
| +static int load_recovery_image_in_mmc(void) |
| +{ |
| + setenv("devname", "mmcblk1p"); |
| + set_bootdev("mmc", 1, 0); |
| + return load_kernel((uint8_t *)CONFIG_LOADADDR, 0x01000000); |
| +} |
| + |
| +static int load_recovery_image_in_usb(void) |
| +{ |
| + setenv("devname", "sda"); |
| + set_bootdev("usb", 0, 0); |
| + return load_kernel((uint8_t *)CONFIG_LOADADDR, 0x01000000); |
| +} |
| + |
| +static int show_screen(ScreenIndex scr) |
| +{ |
| + static ScreenIndex cur_scr; |
| + if (cur_scr == scr) { |
| + return 0; |
| + } else { |
| + cur_scr = scr; |
| + return display_screen_in_bmpblk( |
| + (uint8_t *)(TEXT_BASE + CONFIG_OFFSET_GBB), scr); |
|
Che-Liang Chiou
2011/03/09 02:37:53
This address of GBB might not be valid. Please use
Tom Wai-Hong Tam
2011/03/09 10:15:05
Done.
|
| + } |
| +} |
| + |
| +int do_cros_rec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| +{ |
| + ScreenIndex scr; |
|
Che-Liang Chiou
2011/03/09 02:37:53
What's scr used for? I don't see any use of it exc
Tom Wai-Hong Tam
2011/03/09 10:15:05
My mistake. Fixed.
|
| + WARN_ON_FAILURE(write_log()); |
| + WARN_ON_FAILURE(clear_ram_not_in_use()); |
| + |
| + g_is_dev = is_developer_mode_gpio_asserted(); |
| + |
| + if (!g_is_dev) { |
| + while (is_mmc_storage_present() || is_usb_storage_present()) { |
| + scr = SCREEN_RECOVERY_MODE; |
|
Che-Liang Chiou
2011/03/09 06:55:26
Never use this variable hereafter.
Tom Wai-Hong Tam
2011/03/09 10:15:05
Fixed.
|
| + WARN_ON_FAILURE(show_screen(SCREEN_RECOVERY_MODE)); |
| + sleep_ms(200); |
| + } |
| + } |
| + |
| + for (;;) { |
| + while (!is_mmc_storage_present() && !is_usb_storage_present()) { |
| + WARN_ON_FAILURE(show_screen(SCREEN_RECOVERY_NO_OS)); |
| + sleep_ms(200); |
| + } |
| + if (is_mmc_storage_present()) { |
| + WARN_ON_FAILURE(load_recovery_image_in_mmc()); |
| + } |
| + if (is_usb_storage_present()) { |
| + WARN_ON_FAILURE(load_recovery_image_in_usb()); |
| + } |
| + WARN_ON_FAILURE(show_screen(SCREEN_RECOVERY_MISSING_OS)); |
| + sleep_ms(100); |
| + } |
| + |
| + /* This point is never reached */ |
| + return 0; |
| +} |
| + |
| +U_BOOT_CMD(cros_rec, 1, 1, do_cros_rec, "cros_rec", "long help"); |