mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Enhance bootmeth_cros
-----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmTaruARHHNqZ0BjaHJv bWl1bS5vcmcACgkQfxc6PpAIreaQOAgAwTVdxgRsShSbYrpq+xqqtIjo+UJueVRe FydmjArSh9qVOsXMtKTBFtHoc6AHFRcult1aybfd4POPz3utrBH0rUkPO/p7Tkpb RZzwf9Rw1Ie5M2nMA0gBhi1RMBA53S45aeQwS+rMNZgUn20d5NUXSelur84m83C4 QNOD2BBxgNEhAPz1aTqbGZ7qYbLDqLjyorD424iO5xuAq5oZ37XtRRY5AWQr8QyL r+a9pCKwcQF4b243gOVezD5BSMUZKdoLVaJHAUZ+ycn+FuAnwU0G9AIs7lu7Fy7T /5ErJwsNLB31DxRUCCmVdyor3P5rDNqKTf0KcfjyoHSZXSLlAW+zNw== =2Kpk -----END PGP SIGNATURE----- Merge tag 'dm-next-14aug23' of https://source.denx.de/u-boot/custodians/u-boot-dm into next Enhance bootmeth_cros
This commit is contained in:
commit
51171cdd6d
13 changed files with 845 additions and 107 deletions
|
@ -62,41 +62,4 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
|
|||
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
|
||||
ulong initrd_addr, ulong initrd_size, ulong cmdline_force);
|
||||
|
||||
/**
|
||||
* zimage_dump() - Dump the metadata of a zimage
|
||||
*
|
||||
* This shows all available information in a zimage that has been loaded.
|
||||
*
|
||||
* @base_ptr: Pointer to the boot parameters, typically at address
|
||||
* DEFAULT_SETUP_BASE
|
||||
*/
|
||||
void zimage_dump(struct boot_params *base_ptr);
|
||||
|
||||
/**
|
||||
* zboot_start() - Boot a zimage
|
||||
*
|
||||
* Boot a zimage, given the component parts
|
||||
*
|
||||
* @addr: Address where the bzImage is moved before booting, either
|
||||
* BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
|
||||
* @base: Pointer to the boot parameters, typically at address
|
||||
* DEFAULT_SETUP_BASE
|
||||
* @initrd: Address of the initial ramdisk, or 0 if none
|
||||
* @initrd_size: Size of the initial ramdisk, or 0 if none
|
||||
* @cmdline: Command line to use for booting
|
||||
* Return: -EFAULT on error (normally it does not return)
|
||||
*/
|
||||
int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
|
||||
ulong base, char *cmdline);
|
||||
|
||||
/*
|
||||
* zimage_get_kernel_version() - Get the version string from a kernel
|
||||
*
|
||||
* @params: boot_params pointer
|
||||
* @kernel_base: base address of kernel
|
||||
* Return: Kernel version as a NUL-terminated string
|
||||
*/
|
||||
const char *zimage_get_kernel_version(struct boot_params *params,
|
||||
void *kernel_base);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -692,7 +692,7 @@ static void show_loader(struct setup_header *hdr)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
void zimage_dump(struct boot_params *base_ptr)
|
||||
void zimage_dump(struct boot_params *base_ptr, bool show_cmdline)
|
||||
{
|
||||
struct setup_header *hdr;
|
||||
const char *version;
|
||||
|
@ -703,7 +703,7 @@ void zimage_dump(struct boot_params *base_ptr)
|
|||
|
||||
printf("E820: %d entries\n", base_ptr->e820_entries);
|
||||
if (base_ptr->e820_entries) {
|
||||
printf("%18s %16s %s\n", "Addr", "Size", "Type");
|
||||
printf("%12s %10s %s\n", "Addr", "Size", "Type");
|
||||
for (i = 0; i < base_ptr->e820_entries; i++) {
|
||||
struct e820_entry *entry = &base_ptr->e820_map[i];
|
||||
|
||||
|
@ -749,7 +749,7 @@ void zimage_dump(struct boot_params *base_ptr)
|
|||
print_num("Ext loader ver", hdr->ext_loader_ver);
|
||||
print_num("Ext loader type", hdr->ext_loader_type);
|
||||
print_num("Command line ptr", hdr->cmd_line_ptr);
|
||||
if (hdr->cmd_line_ptr) {
|
||||
if (show_cmdline && hdr->cmd_line_ptr) {
|
||||
printf(" ");
|
||||
/* Use puts() to avoid limits from CONFIG_SYS_PBSIZE */
|
||||
puts((char *)(ulong)hdr->cmd_line_ptr);
|
||||
|
@ -787,7 +787,7 @@ static int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
printf("No zboot setup_base\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
zimage_dump(base_ptr);
|
||||
zimage_dump(base_ptr, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -464,8 +464,8 @@ config BOOTMETH_GLOBAL
|
|||
|
||||
config BOOTMETH_CROS
|
||||
bool "Bootdev support for Chromium OS"
|
||||
depends on X86 || SANDBOX
|
||||
default y
|
||||
depends on X86 || ARM || SANDBOX
|
||||
default y if !ARM
|
||||
help
|
||||
Enables support for booting Chromium OS using bootdevs. This uses the
|
||||
kernel A slot and obtains the kernel command line from the parameters
|
||||
|
|
|
@ -432,6 +432,7 @@ void bootflow_free(struct bootflow *bflow)
|
|||
free(bflow->buf);
|
||||
free(bflow->os_name);
|
||||
free(bflow->fdt_fname);
|
||||
free(bflow->bootmeth_priv);
|
||||
}
|
||||
|
||||
void bootflow_remove(struct bootflow *bflow)
|
||||
|
@ -444,6 +445,22 @@ void bootflow_remove(struct bootflow *bflow)
|
|||
free(bflow);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||
int bootflow_read_all(struct bootflow *bflow)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bflow->state != BOOTFLOWST_READY)
|
||||
return log_msg_ret("rd", -EPROTO);
|
||||
|
||||
ret = bootmeth_read_all(bflow->method, bflow);
|
||||
if (ret)
|
||||
return log_msg_ret("rd2", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* BOOTSTD_FULL */
|
||||
|
||||
int bootflow_boot(struct bootflow *bflow)
|
||||
{
|
||||
int ret;
|
||||
|
|
37
boot/bootm.c
37
boot/bootm.c
|
@ -823,6 +823,43 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int bootm_boot_start(ulong addr, const char *cmdline)
|
||||
{
|
||||
static struct cmd_tbl cmd = {"bootm"};
|
||||
char addr_str[30];
|
||||
char *argv[] = {addr_str, NULL};
|
||||
int states;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* TODO(sjg@chromium.org): This uses the command-line interface, but
|
||||
* should not. To clean this up, the various bootm states need to be
|
||||
* passed an info structure instead of cmdline flags. Then this can
|
||||
* set up the required info and move through the states without needing
|
||||
* the command line.
|
||||
*/
|
||||
states = BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_PRE_LOAD |
|
||||
BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS |
|
||||
BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO |
|
||||
BOOTM_STATE_OS_GO;
|
||||
if (IS_ENABLED(CONFIG_SYS_BOOT_RAMDISK_HIGH))
|
||||
states |= BOOTM_STATE_RAMDISK;
|
||||
if (IS_ENABLED(CONFIG_PPC) || IS_ENABLED(CONFIG_MIPS))
|
||||
states |= BOOTM_STATE_OS_CMDLINE;
|
||||
images.state |= states;
|
||||
|
||||
snprintf(addr_str, sizeof(addr_str), "%lx", addr);
|
||||
|
||||
ret = env_set("bootargs", cmdline);
|
||||
if (ret) {
|
||||
printf("Failed to set cmdline\n");
|
||||
return ret;
|
||||
}
|
||||
ret = do_bootm_states(&cmd, 0, 1, argv, states, &images, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
|
||||
/**
|
||||
* image_get_kernel - verify legacy format kernel image
|
||||
|
|
|
@ -61,6 +61,18 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
|
|||
return ops->set_bootflow(dev, bflow, buf, size);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||
int bootmeth_read_all(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
|
||||
|
||||
if (!ops->read_all)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->read_all(dev, bflow);
|
||||
}
|
||||
#endif /* BOOTSTD_FULL */
|
||||
|
||||
int bootmeth_boot(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
|
||||
|
|
|
@ -12,24 +12,76 @@
|
|||
#include <blk.h>
|
||||
#include <bootdev.h>
|
||||
#include <bootflow.h>
|
||||
#include <bootm.h>
|
||||
#include <bootmeth.h>
|
||||
#include <display_options.h>
|
||||
#include <dm.h>
|
||||
#include <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <part.h>
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/zimage.h>
|
||||
#endif
|
||||
#include <linux/sizes.h>
|
||||
#include "bootmeth_cros.h"
|
||||
|
||||
/*
|
||||
* Layout of the ChromeOS kernel
|
||||
*
|
||||
* Partitions 2 and 4 contain kernels
|
||||
*
|
||||
* Contents are:
|
||||
*
|
||||
* Offset Contents
|
||||
* 0 struct vb2_keyblock
|
||||
* m struct vb2_kernel_preamble
|
||||
* m + n kernel buffer
|
||||
*
|
||||
* m is keyblock->keyblock_size
|
||||
* n is preamble->preamble_size
|
||||
*
|
||||
* The kernel buffer itself consists of various parts:
|
||||
*
|
||||
* Offset Contents
|
||||
* m + n kernel image (Flat vmlinux binary or FIT)
|
||||
* b - 8KB Command line text
|
||||
* b - 4KB X86 setup block (struct boot_params, extends for about 16KB)
|
||||
* b X86 bootloader (continuation of setup block)
|
||||
* b + 16KB X86 setup block (copy, used for hold data pointed to)
|
||||
*
|
||||
* b is m + n + preamble->bootloader_address - preamble->body_load_address
|
||||
*
|
||||
* Useful metadata extends from b - 8KB through to b + 32 KB
|
||||
*/
|
||||
|
||||
enum {
|
||||
/* Offsets in the kernel-partition header */
|
||||
KERN_START = 0x4f0,
|
||||
KERN_SIZE = 0x518,
|
||||
PROBE_SIZE = SZ_4K, /* initial bytes read from partition */
|
||||
|
||||
SETUP_OFFSET = 0x1000, /* bytes before base */
|
||||
CMDLINE_OFFSET = 0x2000, /* bytes before base */
|
||||
OFFSET_BASE = 0x100000, /* assumed kernel load-address */
|
||||
X86_SETUP_OFFSET = -0x1000, /* setup offset relative to base */
|
||||
CMDLINE_OFFSET = -0x2000, /* cmdline offset relative to base */
|
||||
X86_KERNEL_OFFSET = 0x4000, /* kernel offset relative to base */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cros_priv - Private data
|
||||
*
|
||||
* This is read from the disk and recorded for use when the full kernel must
|
||||
* be loaded and booted
|
||||
*
|
||||
* @body_offset: Offset of kernel body from start of partition (in bytes)
|
||||
* @body_size: Size of kernel body in bytes
|
||||
* @part_start: Block offset of selected partition from the start of the disk
|
||||
* @body_load_address: Nominal load address for kernel body
|
||||
* @bootloader_address: Address of bootloader, after body is loaded at
|
||||
* body_load_address
|
||||
* @bootloader_size: Size of bootloader in bytes
|
||||
* @info_buf: Buffer containing ChromiumOS info
|
||||
*/
|
||||
struct cros_priv {
|
||||
ulong body_offset;
|
||||
ulong body_size;
|
||||
lbaint_t part_start;
|
||||
ulong body_load_address;
|
||||
ulong bootloader_address;
|
||||
ulong bootloader_size;
|
||||
void *info_buf;
|
||||
};
|
||||
|
||||
static int cros_check(struct udevice *dev, struct bootflow_iter *iter)
|
||||
|
@ -77,61 +129,83 @@ static int copy_cmdline(const char *from, const char *uuid, char **bufp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
|
||||
/**
|
||||
* scan_part() - Scan a kernel partition to see if has a ChromeOS header
|
||||
*
|
||||
* This reads the first PROBE_SIZE of a partition, loookng for
|
||||
* VB2_KEYBLOCK_MAGIC
|
||||
*
|
||||
* @blk: Block device to scan
|
||||
* @partnum: Partition number to scan
|
||||
* @info: Please to put partition info
|
||||
* @hdrp: Return allocated keyblock header on success
|
||||
*/
|
||||
static int scan_part(struct udevice *blk, int partnum,
|
||||
struct disk_partition *info, struct vb2_keyblock **hdrp)
|
||||
{
|
||||
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
|
||||
ulong base, start, size, setup, cmdline, num_blks, kern_base;
|
||||
struct disk_partition info;
|
||||
const char *uuid = NULL;
|
||||
void *buf, *hdr;
|
||||
struct blk_desc *desc = dev_get_uclass_plat(blk);
|
||||
struct vb2_keyblock *hdr;
|
||||
ulong num_blks;
|
||||
int ret;
|
||||
|
||||
log_debug("starting, part=%d\n", bflow->part);
|
||||
|
||||
/* We consider the whole disk, not any one partition */
|
||||
if (bflow->part)
|
||||
return log_msg_ret("max", -ENOENT);
|
||||
|
||||
/* Check partition 2 */
|
||||
ret = part_get_info(desc, 2, &info);
|
||||
ret = part_get_info(desc, partnum, info);
|
||||
if (ret)
|
||||
return log_msg_ret("part", ret);
|
||||
|
||||
/* Make a buffer for the header information */
|
||||
num_blks = SZ_4K >> desc->log2blksz;
|
||||
num_blks = PROBE_SIZE >> desc->log2blksz;
|
||||
log_debug("Reading header, blk=%s, start=%lx, blocks=%lx\n",
|
||||
bflow->blk->name, (ulong)info.start, num_blks);
|
||||
hdr = memalign(SZ_1K, SZ_4K);
|
||||
blk->name, (ulong)info->start, num_blks);
|
||||
hdr = memalign(SZ_1K, PROBE_SIZE);
|
||||
if (!hdr)
|
||||
return log_msg_ret("hdr", -ENOMEM);
|
||||
ret = blk_read(bflow->blk, info.start, num_blks, hdr);
|
||||
if (ret != num_blks)
|
||||
return log_msg_ret("inf", ret);
|
||||
ret = blk_read(blk, info->start, num_blks, hdr);
|
||||
if (ret != num_blks) {
|
||||
free(hdr);
|
||||
return log_msg_ret("inf", -EIO);
|
||||
}
|
||||
|
||||
if (memcmp("CHROMEOS", hdr, 8))
|
||||
if (memcmp(VB2_KEYBLOCK_MAGIC, hdr->magic, VB2_KEYBLOCK_MAGIC_SIZE)) {
|
||||
free(hdr);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
log_info("Header at %lx\n", (ulong)map_to_sysmem(hdr));
|
||||
start = *(u32 *)(hdr + KERN_START);
|
||||
size = ALIGN(*(u32 *)(hdr + KERN_SIZE), desc->blksz);
|
||||
log_debug("Reading start %lx size %lx\n", start, size);
|
||||
bflow->size = size;
|
||||
*hdrp = hdr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cros_read_buf() - Read information into a buf and parse it
|
||||
*
|
||||
* @bflow: Bootflow to update
|
||||
* @buf: Buffer to use
|
||||
* @size: Size of buffer and number of bytes to read thereinto
|
||||
* @start: Start offset to read from on disk
|
||||
* @before_base: Number of bytes to read before the bootloader base
|
||||
* @uuid: UUID string if supported, else NULL
|
||||
* Return: 0 if OK, -ENOMEM if out of memory, -EIO on read failure
|
||||
*/
|
||||
static int cros_read_buf(struct bootflow *bflow, void *buf, ulong size,
|
||||
loff_t start, ulong before_base, const char *uuid)
|
||||
{
|
||||
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
|
||||
ulong base, setup, cmdline, kern_base;
|
||||
ulong num_blks;
|
||||
int ret;
|
||||
|
||||
buf = memalign(SZ_1K, size);
|
||||
if (!buf)
|
||||
return log_msg_ret("buf", -ENOMEM);
|
||||
num_blks = size >> desc->log2blksz;
|
||||
log_debug("Reading data, blk=%s, start=%lx, blocks=%lx\n",
|
||||
bflow->blk->name, (ulong)info.start, num_blks);
|
||||
ret = blk_read(bflow->blk, (ulong)info.start + 0x80, num_blks, buf);
|
||||
log_debug("Reading info to %lx, blk=%s, size=%lx, blocks=%lx\n",
|
||||
(ulong)map_to_sysmem(buf), bflow->blk->name, size, num_blks);
|
||||
ret = blk_read(bflow->blk, start, num_blks, buf);
|
||||
if (ret != num_blks)
|
||||
return log_msg_ret("inf", ret);
|
||||
base = map_to_sysmem(buf);
|
||||
return log_msg_ret("inf", -EIO);
|
||||
base = map_to_sysmem(buf) + before_base;
|
||||
|
||||
setup = base + start - OFFSET_BASE - SETUP_OFFSET;
|
||||
cmdline = base + start - OFFSET_BASE - CMDLINE_OFFSET;
|
||||
kern_base = base + start - OFFSET_BASE + SZ_16K;
|
||||
log_debug("base %lx setup %lx, cmdline %lx, kern_base %lx\n", base,
|
||||
setup = base + X86_SETUP_OFFSET;
|
||||
cmdline = base + CMDLINE_OFFSET;
|
||||
kern_base = base + X86_KERNEL_OFFSET;
|
||||
log_debug("base %lx setup %lx cmdline %lx kern_base %lx\n", base,
|
||||
setup, cmdline, kern_base);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
|
@ -151,35 +225,211 @@ static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
|
|||
if (!bflow->os_name)
|
||||
return log_msg_ret("os", -ENOMEM);
|
||||
|
||||
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
|
||||
uuid = info.uuid;
|
||||
#endif
|
||||
ret = copy_cmdline(map_sysmem(cmdline, 0), uuid, &bflow->cmdline);
|
||||
if (ret)
|
||||
return log_msg_ret("cmd", ret);
|
||||
bflow->x86_setup = map_sysmem(setup, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cros_read_info() - Read information and fill out the bootflow
|
||||
*
|
||||
* @bflow: Bootflow to update
|
||||
* @uuid: UUID string if supported, else NULL
|
||||
* @preamble: Kernel preamble information
|
||||
* Return: 0 if OK, -ENOMEM if out of memory, -EIO on read failure
|
||||
*/
|
||||
static int cros_read_info(struct bootflow *bflow, const char *uuid,
|
||||
const struct vb2_kernel_preamble *preamble)
|
||||
{
|
||||
struct cros_priv *priv = bflow->bootmeth_priv;
|
||||
struct udevice *blk = bflow->blk;
|
||||
struct blk_desc *desc = dev_get_uclass_plat(blk);
|
||||
ulong offset, size, before_base;
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
log_debug("Kernel preamble at %lx, version major %x, minor %x\n",
|
||||
(ulong)map_to_sysmem(preamble),
|
||||
preamble->header_version_major,
|
||||
preamble->header_version_minor);
|
||||
|
||||
log_debug(" - load_address %lx, bl_addr %lx, bl_size %lx\n",
|
||||
(ulong)preamble->body_load_address,
|
||||
(ulong)preamble->bootloader_address,
|
||||
(ulong)preamble->bootloader_size);
|
||||
|
||||
priv->body_size = preamble->body_signature.data_size;
|
||||
priv->body_load_address = preamble->body_load_address;
|
||||
priv->bootloader_address = preamble->bootloader_address;
|
||||
priv->bootloader_size = preamble->bootloader_size;
|
||||
log_debug("Kernel body at %lx size %lx\n", priv->body_offset,
|
||||
priv->body_size);
|
||||
|
||||
/* Work out how many bytes to read before the bootloader base */
|
||||
before_base = -CMDLINE_OFFSET;
|
||||
|
||||
/* Read the cmdline through to the end of the bootloader */
|
||||
size = priv->bootloader_size + before_base;
|
||||
offset = priv->body_offset +
|
||||
(priv->bootloader_address - priv->body_load_address) +
|
||||
CMDLINE_OFFSET;
|
||||
buf = malloc(size);
|
||||
if (!buf)
|
||||
return log_msg_ret("buf", -ENOMEM);
|
||||
|
||||
ret = cros_read_buf(bflow, buf, size,
|
||||
priv->part_start + (offset >> desc->log2blksz),
|
||||
before_base, uuid);
|
||||
if (ret) {
|
||||
/* Clear this since the buffer is invalid */
|
||||
bflow->x86_setup = NULL;
|
||||
free(buf);
|
||||
return log_msg_ret("pro", ret);
|
||||
}
|
||||
priv->info_buf = buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_read_kernel(struct bootflow *bflow)
|
||||
{
|
||||
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
|
||||
struct cros_priv *priv = bflow->bootmeth_priv;
|
||||
ulong base, setup;
|
||||
ulong num_blks;
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
bflow->size = priv->body_size;
|
||||
|
||||
buf = memalign(SZ_1K, priv->body_size);
|
||||
if (!buf)
|
||||
return log_msg_ret("buf", -ENOMEM);
|
||||
|
||||
/* Check that the header is not smaller than permitted */
|
||||
if (priv->body_offset < PROBE_SIZE)
|
||||
return log_msg_ret("san", EFAULT);
|
||||
|
||||
/* Read kernel body */
|
||||
num_blks = priv->body_size >> desc->log2blksz;
|
||||
log_debug("Reading body to %lx, blk=%s, size=%lx, blocks=%lx\n",
|
||||
(ulong)map_to_sysmem(buf), bflow->blk->name, priv->body_size,
|
||||
num_blks);
|
||||
ret = blk_read(bflow->blk,
|
||||
priv->part_start + (priv->body_offset >> desc->log2blksz),
|
||||
num_blks, buf);
|
||||
if (ret != num_blks)
|
||||
return log_msg_ret("inf", -EIO);
|
||||
base = map_to_sysmem(buf) + priv->bootloader_address -
|
||||
priv->body_load_address;
|
||||
setup = base + X86_SETUP_OFFSET;
|
||||
|
||||
bflow->state = BOOTFLOWST_READY;
|
||||
bflow->buf = buf;
|
||||
bflow->x86_setup = map_sysmem(setup, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_read_bootflow(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
const struct vb2_kernel_preamble *preamble;
|
||||
struct disk_partition info;
|
||||
struct vb2_keyblock *hdr;
|
||||
const char *uuid = NULL;
|
||||
struct cros_priv *priv;
|
||||
int part, ret;
|
||||
|
||||
log_debug("starting, part=%d\n", bflow->part);
|
||||
|
||||
/* We consider the whole disk, not any one partition */
|
||||
if (bflow->part)
|
||||
return log_msg_ret("max", -ENOENT);
|
||||
|
||||
/* Check partition 2 then 4 */
|
||||
part = 2;
|
||||
ret = scan_part(bflow->blk, part, &info, &hdr);
|
||||
if (ret) {
|
||||
part = 4;
|
||||
ret = scan_part(bflow->blk, part, &info, &hdr);
|
||||
if (ret)
|
||||
return log_msg_ret("scan", ret);
|
||||
}
|
||||
bflow->part = part;
|
||||
|
||||
priv = malloc(sizeof(struct cros_priv));
|
||||
if (!priv) {
|
||||
free(hdr);
|
||||
return log_msg_ret("buf", -ENOMEM);
|
||||
}
|
||||
bflow->bootmeth_priv = priv;
|
||||
|
||||
log_info("Selected partition %d, header at %lx\n", bflow->part,
|
||||
(ulong)map_to_sysmem(hdr));
|
||||
|
||||
/* Grab a few things from the preamble */
|
||||
preamble = (void *)hdr + hdr->keyblock_size;
|
||||
priv->body_offset = hdr->keyblock_size + preamble->preamble_size;
|
||||
priv->part_start = info.start;
|
||||
|
||||
/* Now read everything we can learn about kernel */
|
||||
#if CONFIG_IS_ENABLED(PARTITION_UUIDS)
|
||||
uuid = info.uuid;
|
||||
#endif
|
||||
ret = cros_read_info(bflow, uuid, preamble);
|
||||
preamble = NULL;
|
||||
free(hdr);
|
||||
if (ret)
|
||||
return log_msg_ret("inf", ret);
|
||||
bflow->size = priv->body_size;
|
||||
bflow->state = BOOTFLOWST_READY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cros_read_file(struct udevice *dev, struct bootflow *bflow,
|
||||
const char *file_path, ulong addr, ulong *sizep)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(BOOSTD_FULL)
|
||||
static int cros_read_all(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (bflow->buf)
|
||||
return log_msg_ret("ld", -EALREADY);
|
||||
ret = cros_read_kernel(bflow);
|
||||
if (ret)
|
||||
return log_msg_ret("rd", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* BOOSTD_FULL */
|
||||
|
||||
static int cros_boot(struct udevice *dev, struct bootflow *bflow)
|
||||
{
|
||||
#ifdef CONFIG_X86
|
||||
zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
|
||||
map_to_sysmem(bflow->x86_setup),
|
||||
bflow->cmdline);
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
return log_msg_ret("go", -EFAULT);
|
||||
if (!bflow->buf) {
|
||||
ret = cros_read_kernel(bflow);
|
||||
if (ret)
|
||||
return log_msg_ret("rd", ret);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86)) {
|
||||
ret = zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0,
|
||||
map_to_sysmem(bflow->x86_setup),
|
||||
bflow->cmdline);
|
||||
} else {
|
||||
ret = bootm_boot_start(map_to_sysmem(bflow->buf),
|
||||
bflow->cmdline);
|
||||
}
|
||||
|
||||
return log_msg_ret("go", ret);
|
||||
}
|
||||
|
||||
static int cros_bootmeth_bind(struct udevice *dev)
|
||||
|
@ -196,6 +446,9 @@ static struct bootmeth_ops cros_bootmeth_ops = {
|
|||
.read_bootflow = cros_read_bootflow,
|
||||
.read_file = cros_read_file,
|
||||
.boot = cros_boot,
|
||||
#if CONFIG_IS_ENABLED(BOOSTD_FULL)
|
||||
.read_all = cros_read_all,
|
||||
#endif /* BOOSTD_FULL */
|
||||
};
|
||||
|
||||
static const struct udevice_id cros_bootmeth_ids[] = {
|
||||
|
|
197
boot/bootmeth_cros.h
Normal file
197
boot/bootmeth_cros.h
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Structures used by the ChromiumOS bootmeth
|
||||
*
|
||||
* See docs at:
|
||||
* https://www.chromium.org/chromium-os/chromiumos-design-docs/verified-boot-data-structures/
|
||||
*
|
||||
* Original code at:
|
||||
* https://chromium.googlesource.com/chromiumos/platform/vboot_reference/+/refs/heads/main/firmware/2lib/include/2struct.h
|
||||
*
|
||||
* Code taken from vboot_reference commit 5b8596ce file 2struct.h
|
||||
*
|
||||
* Copyright 2023 Google LLC
|
||||
* Written by Simon Glass <sjg@chromium.org>
|
||||
*/
|
||||
|
||||
#ifndef __BOOTMETH_CROS_H
|
||||
#define __BOOTMETH_CROS_H
|
||||
|
||||
/* Signature data (a secure hash, possibly signed) */
|
||||
struct vb2_signature {
|
||||
/* Offset of signature data from start of this struct */
|
||||
uint32_t sig_offset;
|
||||
uint32_t reserved0;
|
||||
|
||||
/* Size of signature data in bytes */
|
||||
uint32_t sig_size;
|
||||
uint32_t reserved1;
|
||||
|
||||
/* Size of the data block which was signed in bytes */
|
||||
uint32_t data_size;
|
||||
uint32_t reserved2;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EXPECTED_VB2_SIGNATURE_SIZE 24
|
||||
|
||||
/* Packed public key data */
|
||||
struct vb2_packed_key {
|
||||
/* Offset of key data from start of this struct */
|
||||
uint32_t key_offset;
|
||||
uint32_t reserved0;
|
||||
|
||||
/* Size of key data in bytes (NOT strength of key in bits) */
|
||||
uint32_t key_size;
|
||||
uint32_t reserved1;
|
||||
|
||||
/* Signature algorithm used by the key (enum vb2_crypto_algorithm) */
|
||||
uint32_t algorithm;
|
||||
uint32_t reserved2;
|
||||
|
||||
/* Key version */
|
||||
uint32_t key_version;
|
||||
uint32_t reserved3;
|
||||
|
||||
/* TODO: when redoing this struct, add a text description of the key */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EXPECTED_VB2_PACKED_KEY_SIZE 32
|
||||
|
||||
#define VB2_KEYBLOCK_MAGIC "CHROMEOS"
|
||||
#define VB2_KEYBLOCK_MAGIC_SIZE 8
|
||||
|
||||
/*
|
||||
* Keyblock, containing the public key used to sign some other chunk of data.
|
||||
*
|
||||
* This should be followed by:
|
||||
* 1) The data_key key data, pointed to by data_key.key_offset.
|
||||
* 2) The checksum data for (vb2_keyblock + data_key data), pointed to
|
||||
* by keyblock_checksum.sig_offset.
|
||||
* 3) The signature data for (vb2_keyblock + data_key data), pointed to
|
||||
* by keyblock_signature.sig_offset.
|
||||
*/
|
||||
struct vb2_keyblock {
|
||||
/* Magic number */
|
||||
uint8_t magic[VB2_KEYBLOCK_MAGIC_SIZE];
|
||||
|
||||
/* Version of this header format */
|
||||
uint32_t header_version_major;
|
||||
uint32_t header_version_minor;
|
||||
|
||||
/*
|
||||
* Length of this entire keyblock, including keys, signatures, and
|
||||
* padding, in bytes
|
||||
*/
|
||||
uint32_t keyblock_size;
|
||||
uint32_t reserved0;
|
||||
|
||||
/*
|
||||
* Signature for this keyblock (header + data pointed to by data_key)
|
||||
* For use with signed data keys
|
||||
*/
|
||||
struct vb2_signature keyblock_signature;
|
||||
|
||||
/*
|
||||
* SHA-512 hash for this keyblock (header + data pointed to by
|
||||
* data_key) For use with unsigned data keys.
|
||||
*
|
||||
* Only supported for kernel keyblocks, not firmware keyblocks.
|
||||
*/
|
||||
struct vb2_signature keyblock_hash;
|
||||
|
||||
/* Flags for key (VB2_KEYBLOCK_FLAG_*) */
|
||||
uint32_t keyblock_flags;
|
||||
uint32_t reserved1;
|
||||
|
||||
/* Key to verify the chunk of data */
|
||||
struct vb2_packed_key data_key;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EXPECTED_VB2_KEYBLOCK_SIZE 112
|
||||
|
||||
/*
|
||||
* Preamble block for kernel, version 2.2
|
||||
*
|
||||
* This should be followed by:
|
||||
* 1) The signature data for the kernel body, pointed to by
|
||||
* body_signature.sig_offset.
|
||||
* 2) The signature data for (vb2_kernel_preamble + body signature data),
|
||||
* pointed to by preamble_signature.sig_offset.
|
||||
* 3) The 16-bit vmlinuz header, which is used for reconstruction of
|
||||
* vmlinuz image.
|
||||
*/
|
||||
struct vb2_kernel_preamble {
|
||||
/*
|
||||
* Size of this preamble, including keys, signatures, vmlinuz header,
|
||||
* and padding, in bytes
|
||||
*/
|
||||
uint32_t preamble_size;
|
||||
uint32_t reserved0;
|
||||
|
||||
/* Signature for this preamble (header + body signature) */
|
||||
struct vb2_signature preamble_signature;
|
||||
|
||||
/* Version of this header format */
|
||||
uint32_t header_version_major;
|
||||
uint32_t header_version_minor;
|
||||
|
||||
/* Kernel version */
|
||||
uint32_t kernel_version;
|
||||
uint32_t reserved1;
|
||||
|
||||
/* Load address for kernel body */
|
||||
uint64_t body_load_address;
|
||||
/* TODO (vboot 2.1): we never used that */
|
||||
|
||||
/* Address of bootloader, after body is loaded at body_load_address */
|
||||
uint64_t bootloader_address;
|
||||
/* TODO (vboot 2.1): should be a 32-bit offset */
|
||||
|
||||
/* Size of bootloader in bytes */
|
||||
uint32_t bootloader_size;
|
||||
uint32_t reserved2;
|
||||
|
||||
/* Signature for the kernel body */
|
||||
struct vb2_signature body_signature;
|
||||
|
||||
/*
|
||||
* TODO (vboot 2.1): fields for kernel offset and size. Right now the
|
||||
* size is implicitly the same as the size of data signed by the body
|
||||
* signature, and the offset is implicitly at the end of the preamble.
|
||||
* But that forces us to pad the preamble to 64KB rather than just
|
||||
* having a tiny preamble and an offset field.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fields added in header version 2.1. You must verify the header
|
||||
* version before reading these fields!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Address of 16-bit header for vmlinuz reassembly. Readers should
|
||||
* return 0 for header version < 2.1.
|
||||
*/
|
||||
uint64_t vmlinuz_header_address;
|
||||
|
||||
/* Size of 16-bit header for vmlinuz in bytes. Readers should return 0
|
||||
for header version < 2.1 */
|
||||
uint32_t vmlinuz_header_size;
|
||||
uint32_t reserved3;
|
||||
|
||||
/*
|
||||
* Fields added in header version 2.2. You must verify the header
|
||||
* version before reading these fields!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Flags; see VB2_KERNEL_PREAMBLE_*. Readers should return 0 for
|
||||
* header version < 2.2. Flags field is currently defined as:
|
||||
* [31:2] - Reserved (for future use)
|
||||
* [1:0] - Kernel image type (0b00 - CrOS,
|
||||
* 0b01 - bootimg,
|
||||
* 0b10 - multiboot)
|
||||
*/
|
||||
uint32_t flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* __BOOTMETH_CROS_H */
|
|
@ -9,6 +9,7 @@
|
|||
#include <common.h>
|
||||
#include <bootdev.h>
|
||||
#include <bootflow.h>
|
||||
#include <bootm.h>
|
||||
#include <bootstd.h>
|
||||
#include <command.h>
|
||||
#include <console.h>
|
||||
|
@ -303,11 +304,14 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
{
|
||||
struct bootstd_priv *std;
|
||||
struct bootflow *bflow;
|
||||
bool x86_setup = false;
|
||||
bool dump = false;
|
||||
int ret;
|
||||
|
||||
if (argc > 1 && *argv[1] == '-')
|
||||
if (argc > 1 && *argv[1] == '-') {
|
||||
dump = strchr(argv[1], 'd');
|
||||
x86_setup = strchr(argv[1], 's');
|
||||
}
|
||||
|
||||
ret = bootstd_get_priv(&std);
|
||||
if (ret)
|
||||
|
@ -319,6 +323,12 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
}
|
||||
bflow = std->cur_bootflow;
|
||||
|
||||
if (IS_ENABLED(CONFIG_X86) && x86_setup) {
|
||||
zimage_dump(bflow->x86_setup, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Name: %s\n", bflow->name);
|
||||
printf("Device: %s\n", bflow->dev->name);
|
||||
printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)");
|
||||
|
@ -369,6 +379,35 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int do_bootflow_read(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
struct bootstd_priv *std;
|
||||
struct bootflow *bflow;
|
||||
int ret;
|
||||
|
||||
ret = bootstd_get_priv(&std);
|
||||
if (ret)
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
/*
|
||||
* Require a current bootflow. Users can use 'bootflow scan -b' to
|
||||
* automatically scan and boot, if needed.
|
||||
*/
|
||||
if (!std->cur_bootflow) {
|
||||
printf("No bootflow selected\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
bflow = std->cur_bootflow;
|
||||
ret = bootflow_read_all(bflow);
|
||||
if (ret) {
|
||||
printf("Failed: err=%dE\n", ret);
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||
char *const argv[])
|
||||
{
|
||||
|
@ -508,8 +547,9 @@ static char bootflow_help_text[] =
|
|||
"scan [-abeGl] [bdev] - scan for valid bootflows (-l list, -a all, -e errors, -b boot, -G no global)\n"
|
||||
"bootflow list [-e] - list scanned bootflows (-e errors)\n"
|
||||
"bootflow select [<num>|<name>] - select a bootflow\n"
|
||||
"bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n"
|
||||
"bootflow boot - boot current bootflow (or first available if none selected)\n"
|
||||
"bootflow info [-ds] - show info on current bootflow (-d dump bootflow)\n"
|
||||
"bootflow read - read all current-bootflow files\n"
|
||||
"bootflow boot - boot current bootflow\n"
|
||||
"bootflow menu [-t] - show a menu of available bootflows\n"
|
||||
"bootflow cmdline [set|get|clear|delete|auto] <param> [<value>] - update cmdline";
|
||||
#else
|
||||
|
@ -523,6 +563,7 @@ U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text,
|
|||
U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list),
|
||||
U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select),
|
||||
U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
|
||||
U_BOOT_SUBCMD_MKENT(read, 1, 1, do_bootflow_read),
|
||||
U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
|
||||
U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
|
||||
U_BOOT_SUBCMD_MKENT(cmdline, 4, 1, do_bootflow_cmdline),
|
||||
|
|
|
@ -11,7 +11,8 @@ Synopis
|
|||
bootflow scan [-abelGH] [bootdev]
|
||||
bootflow list [-e]
|
||||
bootflow select [<num|name>]
|
||||
bootflow info [-d]
|
||||
bootflow info [-ds]
|
||||
bootflow read
|
||||
bootflow boot
|
||||
bootflow cmdline [set|get|clear|delete|auto] <param> [<value>]
|
||||
|
||||
|
@ -191,11 +192,29 @@ Error
|
|||
|
||||
Use the `-d` flag to dump out the contents of the bootfile file.
|
||||
|
||||
The `-s` flag shows any x86 setup block, instead of the above.
|
||||
|
||||
|
||||
bootflow read
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This reads any files related to the bootflow. Some bootflows with large files
|
||||
avoid doing this when the bootflow is scanned, since it uses a lot of memory
|
||||
and takes extra time. The files are then automatically read when `bootflow boot`
|
||||
is used.
|
||||
|
||||
This command reads these files immediately. Typically this fills in the bootflow
|
||||
`buf` property, which can be used to examine the bootflow.
|
||||
|
||||
Note that reading the files does not result in any extra parsing, nor loading of
|
||||
images in the files. This is purely used to read in the data ready for
|
||||
booting, or examination.
|
||||
|
||||
|
||||
bootflow boot
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This boots the current bootflow.
|
||||
This boots the current bootflow, reading any required files first.
|
||||
|
||||
|
||||
bootflow cmdline
|
||||
|
@ -522,6 +541,122 @@ the cmdline is word-wrapped here and some parts of the command line are elided::
|
|||
[ 0.000000] Command line: loglevel=7 ... usb-storage.quirks=13fe:6500:u earlycon=uart8250,mmio32,0xfe03e000,115200n8
|
||||
[ 0.000000] x86/split lock detection: warning about user-space split_locks
|
||||
|
||||
This shows looking at x86 setup information::
|
||||
|
||||
=> bootfl sel 0
|
||||
=> bootfl i -s
|
||||
Setup located at 77b56010:
|
||||
|
||||
ACPI RSDP addr : 0
|
||||
E820: 2 entries
|
||||
Addr Size Type
|
||||
0 1000 RAM
|
||||
fffff000 1000 Reserved
|
||||
Setup sectors : 1e
|
||||
Root flags : 1
|
||||
Sys size : 63420
|
||||
RAM size : 0
|
||||
Video mode : ffff
|
||||
Root dev : 0
|
||||
Boot flag : 0
|
||||
Jump : 66eb
|
||||
Header : 53726448
|
||||
Kernel V2
|
||||
Version : 20d
|
||||
Real mode switch : 0
|
||||
Start sys seg : 1000
|
||||
Kernel version : 38cc
|
||||
@00003acc:
|
||||
Type of loader : ff
|
||||
unknown
|
||||
Load flags : 1
|
||||
: loaded-high
|
||||
Setup move size : 8000
|
||||
Code32 start : 100000
|
||||
Ramdisk image : 0
|
||||
Ramdisk size : 0
|
||||
Bootsect kludge : 0
|
||||
Heap end ptr : 5160
|
||||
Ext loader ver : 0
|
||||
Ext loader type : 0
|
||||
Command line ptr : 735000
|
||||
Initrd addr max : 7fffffff
|
||||
Kernel alignment : 200000
|
||||
Relocatable kernel : 1
|
||||
Min alignment : 15
|
||||
: 200000
|
||||
Xload flags : 3
|
||||
: 64-bit-entry can-load-above-4gb
|
||||
Cmdline size : 7ff
|
||||
Hardware subarch : 0
|
||||
HW subarch data : 0
|
||||
Payload offset : 26e
|
||||
Payload length : 612045
|
||||
Setup data : 0
|
||||
Pref address : 1000000
|
||||
Init size : 1383000
|
||||
Handover offset : 0
|
||||
|
||||
This shows reading a bootflow to examine the kernel::
|
||||
|
||||
=> bootfl i 0
|
||||
Name:
|
||||
Device: emmc@1c,0.bootdev
|
||||
Block dev: emmc@1c,0.blk
|
||||
Method: cros
|
||||
State: ready
|
||||
Partition: 2
|
||||
Subdir: (none)
|
||||
Filename: <NULL>
|
||||
Buffer: 0
|
||||
Size: 63ee00 (6548992 bytes)
|
||||
OS: ChromeOS
|
||||
Cmdline: console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
|
||||
X86 setup: 77b56010
|
||||
Logo: (none)
|
||||
FDT: <NULL>
|
||||
Error: 0
|
||||
|
||||
Note that `Buffer` is 0 so it has not be read yet. Using `bootflow read`::
|
||||
|
||||
=> bootfl read
|
||||
=> bootfl info
|
||||
Name:
|
||||
Device: emmc@1c,0.bootdev
|
||||
Block dev: emmc@1c,0.blk
|
||||
Method: cros
|
||||
State: ready
|
||||
Partition: 2
|
||||
Subdir: (none)
|
||||
Filename: <NULL>
|
||||
Buffer: 77b7e400
|
||||
Size: 63ee00 (6548992 bytes)
|
||||
OS: ChromeOS
|
||||
Cmdline: console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off
|
||||
X86 setup: 781b4400
|
||||
Logo: (none)
|
||||
FDT: <NULL>
|
||||
Error: 0
|
||||
|
||||
Now the buffer can be accessed::
|
||||
|
||||
=> md 77b7e400
|
||||
77b7e400: 1186f6fc 40000002 b8fa0c75 00000018 .......@u.......
|
||||
77b7e410: c08ed88e a68dd08e 000001e8 000000e8 ................
|
||||
77b7e420: ed815d00 00000021 62c280b8 89e80100 .]..!......b....
|
||||
77b7e430: 22f7e8c4 c0850061 22ec850f eb890061 ..."a......"a...
|
||||
77b7e440: 0230868b 01480000 21d0f7c3 00fb81c3 ..0...H....!....
|
||||
77b7e450: 7d010000 0000bb05 c3810100 00d4f000 ...}............
|
||||
77b7e460: 8130858d 85890061 00618132 3095010f ..0.a...2.a....0
|
||||
77b7e470: 0f006181 c883e020 e0220f20 e000bb8d .a.. ... .".....
|
||||
77b7e480: c0310062 001800b9 8dabf300 62e000bb b.1............b
|
||||
77b7e490: 07878d00 89000010 00bb8d07 8d0062f0 .............b..
|
||||
77b7e4a0: 00100787 0004b900 07890000 00100005 ................
|
||||
77b7e4b0: 08c78300 8df37549 630000bb 0183b800 ....Iu.....c....
|
||||
77b7e4c0: 00b90000 89000008 00000507 c7830020 ............ ...
|
||||
77b7e4d0: f3754908 e000838d 220f0062 0080b9d8 .Iu.....b.."....
|
||||
77b7e4e0: 320fc000 08e8ba0f c031300f b8d0000f ...2.....01.....
|
||||
77b7e4f0: 00000020 6ad8000f 00858d10 50000002 ......j.......P
|
||||
|
||||
|
||||
Return value
|
||||
|
|
|
@ -83,6 +83,7 @@ enum bootflow_flags_t {
|
|||
* @flags: Flags for the bootflow (see enum bootflow_flags_t)
|
||||
* @cmdline: OS command line, or NULL if not known (allocated)
|
||||
* @x86_setup: Pointer to x86 setup block inside @buf, NULL if not present
|
||||
* @bootmeth_priv: Private data for the bootmeth
|
||||
*/
|
||||
struct bootflow {
|
||||
struct list_head bm_node;
|
||||
|
@ -107,7 +108,8 @@ struct bootflow {
|
|||
ulong fdt_addr;
|
||||
int flags;
|
||||
char *cmdline;
|
||||
char *x86_setup;
|
||||
void *x86_setup;
|
||||
void *bootmeth_priv;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -350,6 +352,17 @@ void bootflow_free(struct bootflow *bflow);
|
|||
*/
|
||||
int bootflow_boot(struct bootflow *bflow);
|
||||
|
||||
/**
|
||||
* bootflow_read_all() - Read all bootflow files
|
||||
*
|
||||
* Some bootmeths delay reading of large files until booting is requested. This
|
||||
* causes those files to be read.
|
||||
*
|
||||
* @bflow: Bootflow to read
|
||||
* Return: result of trying to read
|
||||
*/
|
||||
int bootflow_read_all(struct bootflow *bflow);
|
||||
|
||||
/**
|
||||
* bootflow_run_boot() - Try to boot a bootflow
|
||||
*
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <image.h>
|
||||
|
||||
struct boot_params;
|
||||
struct cmd_tbl;
|
||||
|
||||
#define BOOTM_ERR_RESET (-1)
|
||||
|
@ -124,4 +125,50 @@ int bootm_process_cmdline(char *buf, int maxlen, int flags);
|
|||
*/
|
||||
int bootm_process_cmdline_env(int flags);
|
||||
|
||||
/**
|
||||
* zboot_start() - Boot a zimage
|
||||
*
|
||||
* Boot a zimage, given the component parts
|
||||
*
|
||||
* @addr: Address where the bzImage is moved before booting, either
|
||||
* BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR
|
||||
* @base: Pointer to the boot parameters, typically at address
|
||||
* DEFAULT_SETUP_BASE
|
||||
* @initrd: Address of the initial ramdisk, or 0 if none
|
||||
* @initrd_size: Size of the initial ramdisk, or 0 if none
|
||||
* @cmdline: Command line to use for booting
|
||||
* Return: -EFAULT on error (normally it does not return)
|
||||
*/
|
||||
int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size,
|
||||
ulong base, char *cmdline);
|
||||
|
||||
/*
|
||||
* zimage_get_kernel_version() - Get the version string from a kernel
|
||||
*
|
||||
* @params: boot_params pointer
|
||||
* @kernel_base: base address of kernel
|
||||
* Return: Kernel version as a NUL-terminated string
|
||||
*/
|
||||
const char *zimage_get_kernel_version(struct boot_params *params,
|
||||
void *kernel_base);
|
||||
|
||||
/**
|
||||
* zimage_dump() - Dump the metadata of a zimage
|
||||
*
|
||||
* This shows all available information in a zimage that has been loaded.
|
||||
*
|
||||
* @base_ptr: Pointer to the boot parameters, typically at address
|
||||
* DEFAULT_SETUP_BASE
|
||||
* @show_cmdline: true to show the full command line
|
||||
*/
|
||||
void zimage_dump(struct boot_params *base_ptr, bool show_cmdline);
|
||||
|
||||
/*
|
||||
* bootm_boot_start() - Boot an image at the given address
|
||||
*
|
||||
* @addr: Image address
|
||||
* @cmdline: Command line to set
|
||||
*/
|
||||
int bootm_boot_start(ulong addr, const char *cmdline);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,7 +119,16 @@ struct bootmeth_ops {
|
|||
*/
|
||||
int (*read_file)(struct udevice *dev, struct bootflow *bflow,
|
||||
const char *file_path, ulong addr, ulong *sizep);
|
||||
|
||||
#if CONFIG_IS_ENABLED(BOOTSTD_FULL)
|
||||
/**
|
||||
* readall() - read all files for a bootflow
|
||||
*
|
||||
* @dev: Bootmethod device to boot
|
||||
* @bflow: Bootflow to read
|
||||
* Return: 0 if OK, -EIO on I/O error, other -ve on other error
|
||||
*/
|
||||
int (*read_all)(struct udevice *dev, struct bootflow *bflow);
|
||||
#endif /* BOOTSTD_FULL */
|
||||
/**
|
||||
* boot() - boot a bootflow
|
||||
*
|
||||
|
@ -223,6 +232,20 @@ int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
|
|||
int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow,
|
||||
const char *file_path, ulong addr, ulong *sizep);
|
||||
|
||||
/**
|
||||
* bootmeth_read_all() - read all bootflow files
|
||||
*
|
||||
* Some bootmeths delay reading of large files until booting is requested. This
|
||||
* causes those files to be read.
|
||||
*
|
||||
* @dev: Bootmethod device to use
|
||||
* @bflow: Bootflow to read
|
||||
* Return: does not return on success, since it should boot the
|
||||
* Operating Systemn. Returns -EFAULT if that fails, other -ve on
|
||||
* other error
|
||||
*/
|
||||
int bootmeth_read_all(struct udevice *dev, struct bootflow *bflow);
|
||||
|
||||
/**
|
||||
* bootmeth_boot() - boot a bootflow
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue