diff options
author | Che-Liang Chiou <clchiou@chromium.org> | 2011-07-22 20:39:45 +0800 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2011-08-29 10:59:10 -0700 |
commit | cf2414a7b3d7bd2e7ee363fd6e356a3e4d9339a7 (patch) | |
tree | 0c1df789498b09c8bb85371b33aad3f79b6d259e /lib | |
parent | 4ddaee01e37ed491ce7c45586ab96e5bbb905ab4 (diff) |
CHROMIUM: reunify boot_kernel
During the code migration to the redesigned vboot_reference API, the
boot_kernel (formerly named load_kernel_helper) was divided and its
private functions were taken out to keep U-Boot compilable
$ git log --oneline -3 -- lib/chromeos/load_kernel_helper.c
6cdb577 CHROMIUM: remove codes based on deprecated API of vboot_reference
29c5f74 CHROMIUM: Separate cmdline update part from load_kernel_helper library.
f853479 CHROMIUM: Separate the pre-boot FDT update part from load_kernel_helper library.
The commit 29c5f74 and f853479 took out the private functions for
updating kernel command line and embedding crossystem data into a device
tree. The functions are the guts of boot_kernel and serve no purpose
other than helping boot kernel.
In fact, if you diff load_kernel_helper and boot_kernel, you will find
they are virtually identical, except that functions based on deprecated
APIs of vboot_reference are removed in boot_kernel.
As the code migration has been completed, it is time for the private
functions to reunite with the boot_kernel.
BUG=chromium-os:16542
TEST=boot on Aebl
Change-Id: I6512d7a5197c41df7a2e9cc5d90c40be87b468b0
Reviewed-on: http://gerrit.chromium.org/gerrit/4573
Reviewed-by: Che-Liang Chiou <clchiou@chromium.org>
Tested-by: Che-Liang Chiou <clchiou@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chromeos/Makefile | 3 | ||||
-rw-r--r-- | lib/chromeos/boot_kernel.c | 241 | ||||
-rw-r--r-- | lib/chromeos/cmdline_updater.c | 109 | ||||
-rw-r--r-- | lib/chromeos/preboot_fdt_update.c | 44 | ||||
-rw-r--r-- | lib/vboot/Makefile | 3 | ||||
-rw-r--r-- | lib/vboot/main_entry.c | 2 |
6 files changed, 243 insertions, 159 deletions
diff --git a/lib/chromeos/Makefile b/lib/chromeos/Makefile index e21429a399..751bc42df2 100644 --- a/lib/chromeos/Makefile +++ b/lib/chromeos/Makefile @@ -12,12 +12,11 @@ include $(TOPDIR)/config.mk LIB = $(obj)libchromeos.a -COBJS-$(CONFIG_CHROMEOS) += cmdline_updater.o +COBJS-$(CONFIG_CHROMEOS) += boot_kernel.o COBJS-$(CONFIG_CHROMEOS) += crossystem_data.o COBJS-$(CONFIG_CHROMEOS) += fdt_decode.o COBJS-$(CONFIG_CHROMEOS) += firmware_storage_spi.o COBJS-$(CONFIG_CHROMEOS) += memory_wipe.o -COBJS-$(CONFIG_CHROMEOS) += preboot_fdt_update.o # TODO(sjg): This MMC code is not needed as yet, and needs slight changes # to build now diff --git a/lib/chromeos/boot_kernel.c b/lib/chromeos/boot_kernel.c new file mode 100644 index 0000000000..16cd1dc364 --- /dev/null +++ b/lib/chromeos/boot_kernel.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * 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. + */ + +#include <common.h> +#include <part.h> +#include <chromeos/boot_kernel.h> +#include <chromeos/common.h> +#include <chromeos/crossystem_data.h> + +#include <load_kernel_fw.h> +#include <vboot_api.h> + +#define PREFIX "boot_kernel: " + +/* + * We uses a static variable to communicate with fit_update_fdt_before_boot(). + * For more information, please see commit log. + */ +static crossystem_data_t *g_crossystem_data = NULL; + +/* defined in common/cmd_bootm.c */ +int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +/* Maximum kernel command-line size */ +#define CROS_CONFIG_SIZE 4096 + +/* Size of the x86 zeropage table */ +#define CROS_PARAMS_SIZE 4096 + +/* Extra buffer to string replacement */ +#define EXTRA_BUFFER 4096 + +/** + * This loads kernel command line from the buffer that holds the loaded kernel + * image. This function calculates the address of the command line from the + * bootloader address. + * + * @param bootloader_address is the address of the bootloader in the buffer + * @return kernel config address + */ +static char *get_kernel_config(char *bootloader_address) +{ + /* Use the bootloader address to find the kernel config location. */ + return bootloader_address - CROS_PARAMS_SIZE - CROS_CONFIG_SIZE; +} + +static uint32_t get_dev_num(const block_dev_desc_t *dev) +{ + return dev->dev; +} + +/* assert(0 <= val && val < 99); sprintf(dst, "%u", val); */ +static char *itoa(char *dst, int val) +{ + if (val > 9) + *dst++ = '0' + val / 10; + *dst++ = '0' + val % 10; + return dst; +} + +/* copied from x86 bootstub code; sprintf(dst, "%02x", val) */ +static void one_byte(char *dst, uint8_t val) +{ + dst[0] = "0123456789abcdef"[(val >> 4) & 0x0F]; + dst[1] = "0123456789abcdef"[val & 0x0F]; +} + +/* copied from x86 bootstub code; display a GUID in canonical form */ +static char *emit_guid(char *dst, uint8_t *guid) +{ + one_byte(dst, guid[3]); dst += 2; + one_byte(dst, guid[2]); dst += 2; + one_byte(dst, guid[1]); dst += 2; + one_byte(dst, guid[0]); dst += 2; + *dst++ = '-'; + one_byte(dst, guid[5]); dst += 2; + one_byte(dst, guid[4]); dst += 2; + *dst++ = '-'; + one_byte(dst, guid[7]); dst += 2; + one_byte(dst, guid[6]); dst += 2; + *dst++ = '-'; + one_byte(dst, guid[8]); dst += 2; + one_byte(dst, guid[9]); dst += 2; + *dst++ = '-'; + one_byte(dst, guid[10]); dst += 2; + one_byte(dst, guid[11]); dst += 2; + one_byte(dst, guid[12]); dst += 2; + one_byte(dst, guid[13]); dst += 2; + one_byte(dst, guid[14]); dst += 2; + one_byte(dst, guid[15]); dst += 2; + return dst; +} + +/** + * This replaces: + * %D -> device number + * %P -> partition number + * %U -> GUID + * in kernel command line. + * + * For example: + * ("root=/dev/sd%D%P", 2, 3) -> "root=/dev/sdc3" + * ("root=/dev/mmcblk%Dp%P", 0, 5) -> "root=/dev/mmcblk0p5". + * + * @param src - input string + * @param devnum - device number of the storage device we will mount + * @param partnum - partition number of the root file system we will mount + * @param guid - guid of the kernel partition + * @param dst - output string; a copy of [src] with special characters replaced + */ +static void update_cmdline(char *src, int devnum, int partnum, uint8_t *guid, + char *dst) +{ + int c; + + // sanity check on inputs + if (devnum < 0 || devnum > 25 || partnum < 1 || partnum > 99) { + VBDEBUG(PREFIX "insane input: %d, %d\n", devnum, partnum); + devnum = 0; + partnum = 3; + } + + while ((c = *src++)) { + if (c != '%') { + *dst++ = c; + continue; + } + + switch ((c = *src++)) { + case '\0': + /* input ends in '%'; is it not well-formed? */ + src--; + break; + case 'D': + /* + * TODO: Do we have any better way to know whether %D + * is replaced by a letter or digits? So far, this is + * done by a rule of thumb that if %D is followed by a + * 'p' character, then it is replaced by digits. + */ + if (*src == 'p') + dst = itoa(dst, devnum); + else + *dst++ = 'a' + devnum; + break; + case 'P': + dst = itoa(dst, devnum); + break; + case 'U': + dst = emit_guid(dst, guid); + break; + default: + *dst++ = '%'; + *dst++ = c; + break; + } + } + + *dst = '\0'; +} + +/** + * This boots kernel specified in [kparmas]. + * + * @param kparams kparams returned from VbSelectAndLoadKernel() + * @param cdata crossystem data pointer + * @return LOAD_KERNEL_INVALID if it fails to boot; otherwise it never returns + * to its caller + */ +int boot_kernel(VbSelectAndLoadKernelParams *kparams, crossystem_data_t *cdata) +{ + char cmdline_buf[CROS_CONFIG_SIZE + EXTRA_BUFFER]; + char cmdline_out[CROS_CONFIG_SIZE + EXTRA_BUFFER]; + char load_address[32]; + char *argv[2] = {"bootm", load_address}; + char *cmdline; + + /* + * casting bootloader_address of uint64_t type to uintptr_t before + * further casting it to char * to avoid compiler warning "cast to + * pointer from integer of different size" on 32-bit address machine. + */ + cmdline = get_kernel_config((char *) + (uintptr_t)kparams->bootloader_address); + strncpy(cmdline_buf, cmdline, CROS_CONFIG_SIZE); + + /* if we have init bootargs, append it */ + if ((cmdline = getenv("bootargs"))) { + strcat(cmdline_buf, " "); + strncat(cmdline_buf, cmdline, EXTRA_BUFFER - 1); + } + + VBDEBUG(PREFIX "cmdline before update: %s\n", cmdline_buf); + + update_cmdline(cmdline_buf, + get_dev_num(kparams->disk_handle), + kparams->partition_number + 1, + kparams->partition_guid, + cmdline_out); + + setenv("bootargs", cmdline_out); + VBDEBUG(PREFIX "cmdline after update: %s\n", getenv("bootargs")); + + g_crossystem_data = cdata; + + sprintf(load_address, "0x%p", kparams->kernel_buffer); + do_bootm(NULL, 0, sizeof(argv)/sizeof(*argv), argv); + + VBDEBUG(PREFIX "failed to boot; is kernel broken?\n"); + return LOAD_KERNEL_INVALID; +} + +/* + * This function does the last chance FDT update before booting to kernel. + * Currently we modify the FDT by embedding crossystem data. So before + * calling bootm(), g_crossystem_data should be set. + */ +int fit_update_fdt_before_boot(char *fdt, ulong *new_size) +{ + uint32_t ns; + + if (!g_crossystem_data) { + VBDEBUG(PREFIX "warning: g_crossystem_data is NULL\n"); + return 0; + } + + if (crossystem_data_embed_into_fdt(g_crossystem_data, fdt, &ns)) { + VBDEBUG(PREFIX "crossystem_data_embed_into_fdt() failed\n"); + return 0; + } + + *new_size = ns; + return 0; +} diff --git a/lib/chromeos/cmdline_updater.c b/lib/chromeos/cmdline_updater.c deleted file mode 100644 index d431adfb7d..0000000000 --- a/lib/chromeos/cmdline_updater.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * 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. - */ - -#include <common.h> -#include <chromeos/common.h> -#include <chromeos/cmdline_updater.h> - -#define PREFIX "cmdline_updater: " - -/* assert(0 <= val && val < 99); sprintf(dst, "%u", val); */ -static char *itoa(char *dst, int val) -{ - if (val > 9) - *dst++ = '0' + val / 10; - *dst++ = '0' + val % 10; - return dst; -} - -/* copied from x86 bootstub code; sprintf(dst, "%02x", val) */ -static void one_byte(char *dst, uint8_t val) -{ - dst[0] = "0123456789abcdef"[(val >> 4) & 0x0F]; - dst[1] = "0123456789abcdef"[val & 0x0F]; -} - -/* copied from x86 bootstub code; display a GUID in canonical form */ -static char *emit_guid(char *dst, uint8_t *guid) -{ - one_byte(dst, guid[3]); dst += 2; - one_byte(dst, guid[2]); dst += 2; - one_byte(dst, guid[1]); dst += 2; - one_byte(dst, guid[0]); dst += 2; - *dst++ = '-'; - one_byte(dst, guid[5]); dst += 2; - one_byte(dst, guid[4]); dst += 2; - *dst++ = '-'; - one_byte(dst, guid[7]); dst += 2; - one_byte(dst, guid[6]); dst += 2; - *dst++ = '-'; - one_byte(dst, guid[8]); dst += 2; - one_byte(dst, guid[9]); dst += 2; - *dst++ = '-'; - one_byte(dst, guid[10]); dst += 2; - one_byte(dst, guid[11]); dst += 2; - one_byte(dst, guid[12]); dst += 2; - one_byte(dst, guid[13]); dst += 2; - one_byte(dst, guid[14]); dst += 2; - one_byte(dst, guid[15]); dst += 2; - return dst; -} - -/* This replaces %D, %P, and %U in kernel command line */ -void update_cmdline(char *src, int devnum, int partnum, uint8_t *guid, - char *dst) -{ - int c; - - // sanity check on inputs - if (devnum < 0 || devnum > 25 || partnum < 1 || partnum > 99) { - VBDEBUG(PREFIX "insane input: %d, %d\n", devnum, partnum); - devnum = 0; - partnum = 3; - } - - while ((c = *src++)) { - if (c != '%') { - *dst++ = c; - continue; - } - - switch ((c = *src++)) { - case '\0': - /* input ends in '%'; is it not well-formed? */ - src--; - break; - case 'D': - /* - * TODO: Do we have any better way to know whether %D - * is replaced by a letter or digits? So far, this is - * done by a rule of thumb that if %D is followed by a - * 'p' character, then it is replaced by digits. - */ - if (*src == 'p') - dst = itoa(dst, devnum); - else - *dst++ = 'a' + devnum; - break; - case 'P': - dst = itoa(dst, devnum); - break; - case 'U': - dst = emit_guid(dst, guid); - break; - default: - *dst++ = '%'; - *dst++ = c; - break; - } - } - - *dst = '\0'; -} diff --git a/lib/chromeos/preboot_fdt_update.c b/lib/chromeos/preboot_fdt_update.c deleted file mode 100644 index 06615aebba..0000000000 --- a/lib/chromeos/preboot_fdt_update.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * 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. - */ - -#include <common.h> -#include <chromeos/common.h> -#include <chromeos/crossystem_data.h> - -#define PREFIX "preboot_fdt_update: " - -/* - * We uses a static variable to communicate with fit_update_fdt_before_boot(). - * For more information, please see commit log. - */ -static crossystem_data_t *g_crossystem_data = NULL; - -void set_crossystem_data(crossystem_data_t *cdata) -{ - g_crossystem_data = cdata; -} - -int fit_update_fdt_before_boot(char *fdt, ulong *new_size) -{ - uint32_t ns; - - if (!g_crossystem_data) { - VBDEBUG(PREFIX "warning: g_crossystem_data is NULL\n"); - return 0; - } - - if (crossystem_data_embed_into_fdt(g_crossystem_data, fdt, &ns)) { - VBDEBUG(PREFIX "crossystem_data_embed_into_fdt() failed\n"); - return 0; - } - - *new_size = ns; - return 0; -} diff --git a/lib/vboot/Makefile b/lib/vboot/Makefile index 6e0b9c9922..b209529113 100644 --- a/lib/vboot/Makefile +++ b/lib/vboot/Makefile @@ -12,14 +12,11 @@ include $(TOPDIR)/config.mk LIB = $(obj)libvboot.a -COBJS-$(CONFIG_CHROMEOS_VBOOT) += boot_kernel.o COBJS-$(CONFIG_CHROMEOS_VBOOT) += bootstub_entry.o COBJS-$(CONFIG_CHROMEOS_VBOOT) += firmware_cache.o COBJS-$(CONFIG_CHROMEOS_VBOOT) += global_data.o COBJS-$(CONFIG_CHROMEOS_VBOOT) += main_entry.o -COBJS-$(CONFIG_CHROMEOS_TWOSTOP) += boot_kernel.o - COBJS := $(COBJS-y) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/lib/vboot/main_entry.c b/lib/vboot/main_entry.c index c6b67d5ba8..66eff92987 100644 --- a/lib/vboot/main_entry.c +++ b/lib/vboot/main_entry.c @@ -9,8 +9,8 @@ */ #include <common.h> +#include <chromeos/boot_kernel.h> #include <chromeos/common.h> -#include <vboot/boot_kernel.h> #include <vboot/entry_points.h> #include <vboot/global_data.h> #include <vboot_api.h> |