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"); |