diff options
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | doc/develop/bootstd/android.rst | 39 | ||||
-rw-r--r-- | doc/develop/bootstd/index.rst | 1 | ||||
-rw-r--r-- | doc/develop/bootstd/overview.rst | 2 | ||||
-rw-r--r-- | drivers/core/util.c | 14 | ||||
-rw-r--r-- | include/dm/util.h | 8 | ||||
-rw-r--r-- | include/linux/list.h | 15 | ||||
-rw-r--r-- | include/smbios.h | 1 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_fdt.c | 3 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_memory.c | 33 | ||||
-rw-r--r-- | lib/smbios.c | 9 | ||||
-rw-r--r-- | test/dm/bus.c | 5 | ||||
-rw-r--r-- | test/dm/core.c | 9 | ||||
-rw-r--r-- | test/dm/test-fdt.c | 5 |
16 files changed, 97 insertions, 52 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index a6e47e8a217..c2832345ab1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -945,6 +945,7 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-dfu.git F: boot/bootmeth_android.c F: boot/bootmeth_android.h +F: doc/develop/bootstd/android.rst BTRFS M: Marek BehĂșn <kabel@kernel.org> diff --git a/doc/develop/bootstd/android.rst b/doc/develop/bootstd/android.rst new file mode 100644 index 00000000000..41701d5bdff --- /dev/null +++ b/doc/develop/bootstd/android.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +Android Bootmeth +================ + +Android provides a mechanism for booting its Operating System from eMMC storage, +described on `source.android.com <https://source.android.com/docs/core/architecture/bootloader>`_. + +Android has strong requirements about partitioning layout which are described +`here <https://source.android.com/docs/core/architecture/partitions>`_. +Because multiple partitions are required, this bootmeth only operates on whole mmc +devices which have a valid partition table. + +When invoked on a bootdev, this bootmeth searches for the ``misc`` partition in order +to read the *boot mode*, which can be one of following: + +Normal + Boot the regular Android Operating System. + +Recovery + Boot a slimmed down Recovery Operating System. Can be used + to factory reset the device or to apply system updates. + +Bootloader + Stay in U-Boot and wait for fastboot commands from the host. + +After the *boot mode* has been determined, this bootmeth will read the *slot suffix* +from the ``misc`` partition. For details about slots, see +`the AOSP documentation <https://source.android.com/docs/core/ota/ab#slots>`_. + +When both the *boot mode* and the *slot suffix* are known, the bootflow is created. + +When the bootflow is booted, the bootmeth reads the kernel, the boot arguments and +the vendor ramdisk. +It then boots the kernel using bootm. The relevant devicetree blob is extracted +from the ``boot`` partition based on the ``adtb_idx`` environment variable. + +The compatible string "u-boot,android" is used for the driver. It is present +if `CONFIG_BOOTMETH_ANDROID` is enabled. diff --git a/doc/develop/bootstd/index.rst b/doc/develop/bootstd/index.rst index 9d35b567d55..4c4e26ccdb7 100644 --- a/doc/develop/bootstd/index.rst +++ b/doc/develop/bootstd/index.rst @@ -10,6 +10,7 @@ Standard Boot extlinux pxelinux qfw + android cros script sandbox diff --git a/doc/develop/bootstd/overview.rst b/doc/develop/bootstd/overview.rst index ff3cc48eb64..c6f003851b2 100644 --- a/doc/develop/bootstd/overview.rst +++ b/doc/develop/bootstd/overview.rst @@ -429,7 +429,7 @@ Available bootmeth drivers Bootmeth drivers are provided for booting from various media: - - Android bootflow (boot image v4) + - :doc:`Android <android>` bootflow (boot image v4) - :doc:`ChromiumOS <cros>` ChromiumOS boot from a disk - EFI boot using bootefi from disk - EFI boot using boot manager diff --git a/drivers/core/util.c b/drivers/core/util.c index 108a3bc4dac..fa893485a09 100644 --- a/drivers/core/util.c +++ b/drivers/core/util.c @@ -3,23 +3,13 @@ * Copyright (c) 2013 Google, Inc */ +#include <vsprintf.h> #include <dm/device.h> #include <dm/ofnode.h> #include <dm/read.h> #include <dm/util.h> #include <linux/libfdt.h> -#include <vsprintf.h> - -int list_count_items(struct list_head *head) -{ - struct list_head *node; - int count = 0; - - list_for_each(node, head) - count++; - - return count; -} +#include <linux/list.h> #if CONFIG_IS_ENABLED(OF_REAL) int pci_get_devfn(struct udevice *dev) diff --git a/include/dm/util.h b/include/dm/util.h index 95c3527a37c..ec518c51d93 100644 --- a/include/dm/util.h +++ b/include/dm/util.h @@ -17,14 +17,6 @@ struct dm_stats; struct list_head; /** - * list_count_items() - Count number of items in a list - * - * @param head: Head of list - * Return: number of items, or 0 if empty - */ -int list_count_items(struct list_head *head); - -/** * Dump out a tree of all devices starting @uclass * * @dev_name: udevice name diff --git a/include/linux/list.h b/include/linux/list.h index 6910721c005..0f9d939b05f 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -547,6 +547,21 @@ static inline void list_splice_tail_init(struct list_head *list, &pos->member != (head); \ pos = n, n = list_entry(n->member.prev, typeof(*n), member)) +/** + * list_count_nodes - count nodes in the list + * @head: the head for your list. + */ +static inline size_t list_count_nodes(struct list_head *head) +{ + struct list_head *pos; + size_t count = 0; + + list_for_each(pos, head) + count++; + + return count; +} + /* * Double linked lists with a single pointer list head. * Mostly useful for hash tables where the two pointer list head is diff --git a/include/smbios.h b/include/smbios.h index a4fda9df7bd..00119d7a60c 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -105,6 +105,7 @@ struct __packed smbios_type0 { u8 bios_minor_release; u8 ec_major_release; u8 ec_minor_release; + u16 extended_bios_rom_size; char eos[SMBIOS_STRUCT_EOS_BYTES]; }; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 38e64af2531..1179c31bb13 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -220,6 +220,7 @@ config EFI_CAPSULE_ON_DISK config EFI_IGNORE_OSINDICATIONS bool "Ignore OsIndications for CapsuleUpdate on-disk" depends on EFI_CAPSULE_ON_DISK + default y if !EFI_RT_VOLATILE_STORE help There are boards where U-Boot does not support SetVariable at runtime. Select this option if you want to use the capsule-on-disk feature @@ -486,6 +487,7 @@ config EFI_ECPT config EFI_EBBR_2_1_CONFORMANCE bool "Add the EBBRv2.1 conformance entry to the ECPT table" + depends on BOOTMETH_EFI_BOOTMGR depends on EFI_ECPT depends on EFI_LOADER_HII depends on EFI_RISCV_BOOT_PROTOCOL || !RISCV diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index 4ccf2055be3..c5ecade3aeb 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -43,6 +43,9 @@ int efi_get_distro_fdt_name(char *fname, int size, int seq) case 2: prefix = "/dtb/current"; break; + case 3: + prefix = "/dtbs"; + break; default: return log_msg_ret("pref", -EINVAL); } diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 348612c3dad..65d2116381a 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -133,7 +133,7 @@ efi_status_t efi_load_option_dp_join(struct efi_device_path **dp, *dp = efi_dp_concat(tmp_dp, fdt_dp, *dp_size); efi_free_pool(tmp_dp); - if (!dp) + if (!*dp) return EFI_OUT_OF_RESOURCES; *dp_size += efi_dp_size(fdt_dp) + sizeof(END); } diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 12cf23fa3fa..c6f1dd09456 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -127,7 +127,7 @@ static uint64_t desc_get_end(struct efi_mem_desc *desc) */ static void efi_mem_sort(void) { - struct list_head *lhandle; + struct efi_mem_list *lmem; struct efi_mem_list *prevmem = NULL; bool merge_again = true; @@ -136,19 +136,18 @@ static void efi_mem_sort(void) /* Now merge entries that can be merged */ while (merge_again) { merge_again = false; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; - struct efi_mem_desc *prev = &prevmem->desc; + list_for_each_entry(lmem, &efi_mem, link) { + struct efi_mem_desc *prev; struct efi_mem_desc *cur; uint64_t pages; - lmem = list_entry(lhandle, struct efi_mem_list, link); if (!prevmem) { prevmem = lmem; continue; } cur = &lmem->desc; + prev = &prevmem->desc; if ((desc_get_end(cur) == prev->physical_start) && (prev->type == cur->type) && @@ -268,7 +267,7 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, int memory_type, bool overlap_only_ram) { - struct list_head *lhandle; + struct efi_mem_list *lmem; struct efi_mem_list *newlist; bool carve_again; uint64_t carved_pages = 0; @@ -308,11 +307,9 @@ static efi_status_t efi_add_memory_map_pg(u64 start, u64 pages, /* Add our new map */ do { carve_again = false; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; + list_for_each_entry(lmem, &efi_mem, link) { s64 r; - lmem = list_entry(lhandle, struct efi_mem_list, link); r = efi_mem_carve_out(lmem, &newlist->desc, overlap_only_ram); switch (r) { @@ -444,7 +441,7 @@ static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated) */ static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) { - struct list_head *lhandle; + struct efi_mem_list *lmem; /* * Prealign input max address, so we simplify our matching @@ -452,9 +449,7 @@ static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) */ max_addr &= ~EFI_PAGE_MASK; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem = list_entry(lhandle, - struct efi_mem_list, link); + list_for_each_entry(lmem, &efi_mem, link) { struct efi_mem_desc *desc = &lmem->desc; uint64_t desc_len = desc->num_pages << EFI_PAGE_SHIFT; uint64_t desc_end = desc->physical_start + desc_len; @@ -742,9 +737,9 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, efi_uintn_t *descriptor_size, uint32_t *descriptor_version) { + size_t map_entries; efi_uintn_t map_size = 0; - int map_entries = 0; - struct list_head *lhandle; + struct efi_mem_list *lmem; efi_uintn_t provided_map_size; if (!memory_map_size) @@ -752,8 +747,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, provided_map_size = *memory_map_size; - list_for_each(lhandle, &efi_mem) - map_entries++; + map_entries = list_count_nodes(&efi_mem); map_size = map_entries * sizeof(struct efi_mem_desc); @@ -774,10 +768,7 @@ efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size, /* Copy list into array */ /* Return the list in ascending order */ memory_map = &memory_map[map_entries - 1]; - list_for_each(lhandle, &efi_mem) { - struct efi_mem_list *lmem; - - lmem = list_entry(lhandle, struct efi_mem_list, link); + list_for_each_entry(lmem, &efi_mem, link) { *memory_map = lmem->desc; memory_map--; } diff --git a/lib/smbios.c b/lib/smbios.c index 4126466e34a..7c24ea129eb 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -22,6 +22,7 @@ #include <cpu.h> #include <dm/uclass-internal.h> #endif +#include <linux/sizes.h> /* Safeguard for checking that U_BOOT_VERSION_NUM macros are compatible with U_BOOT_DMI */ #if U_BOOT_VERSION_NUM < 2000 || U_BOOT_VERSION_NUM > 2099 || \ @@ -348,7 +349,13 @@ static int smbios_write_type0(ulong *current, int handle, #endif t->bios_release_date = smbios_add_prop(ctx, NULL, U_BOOT_DMI_DATE); #ifdef CONFIG_ROM_SIZE - t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; + if (CONFIG_ROM_SIZE < SZ_16M) { + t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; + } else { + /* CONFIG_ROM_SIZE < 8 GiB */ + t->bios_rom_size = 0xff; + t->extended_bios_rom_size = CONFIG_ROM_SIZE >> 20; + } #endif t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED | BIOS_CHARACTERISTICS_SELECTABLE_BOOT | diff --git a/test/dm/bus.c b/test/dm/bus.c index a338c7f567c..95326f23dad 100644 --- a/test/dm/bus.c +++ b/test/dm/bus.c @@ -14,6 +14,7 @@ #include <dm/test.h> #include <dm/uclass-internal.h> #include <dm/util.h> +#include <linux/list.h> #include <test/test.h> #include <test/ut.h> @@ -27,14 +28,14 @@ static int dm_test_bus_children(struct unit_test_state *uts) struct uclass *uc; ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); - ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + ut_asserteq(num_devices, list_count_nodes(&uc->dev_head)); /* Probe the bus, which should yield 3 more devices */ ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); num_devices += 3; ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); - ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + ut_asserteq(num_devices, list_count_nodes(&uc->dev_head)); ut_assert(!dm_check_devices(uts, num_devices)); diff --git a/test/dm/core.c b/test/dm/core.c index dbad1b317db..5bc5e8e82ec 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -16,6 +16,7 @@ #include <dm/util.h> #include <dm/test.h> #include <dm/uclass-internal.h> +#include <linux/list.h> #include <test/test.h> #include <test/ut.h> @@ -123,15 +124,15 @@ static int dm_test_autobind(struct unit_test_state *uts) * device with no children. */ ut_assert(uts->root); - ut_asserteq(1, list_count_items(gd->uclass_root)); - ut_asserteq(0, list_count_items(&gd->dm_root->child_head)); + ut_asserteq(1, list_count_nodes(gd->uclass_root)); + ut_asserteq(0, list_count_nodes(&gd->dm_root->child_head)); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); ut_assertok(dm_scan_plat(false)); /* We should have our test class now at least, plus more children */ - ut_assert(1 < list_count_items(gd->uclass_root)); - ut_assert(0 < list_count_items(&gd->dm_root->child_head)); + ut_assert(1 < list_count_nodes(gd->uclass_root)); + ut_assert(0 < list_count_nodes(&gd->dm_root->child_head)); /* Our 3 dm_test_infox children should be bound to the test uclass */ ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 18c89eef43f..31effff59c2 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -19,6 +19,7 @@ #include <dm/util.h> #include <dm/of_access.h> #include <linux/ioport.h> +#include <linux/list.h> #include <test/test.h> #include <test/ut.h> @@ -162,7 +163,7 @@ static int dm_test_fdt(struct unit_test_state *uts) ut_assert(!ret); /* These are num_devices compatible root-level device tree nodes */ - ut_asserteq(num_devices, list_count_items(&uc->dev_head)); + ut_asserteq(num_devices, list_count_nodes(&uc->dev_head)); /* Each should have platform data but no private data */ for (i = 0; i < num_devices; i++) { @@ -217,7 +218,7 @@ static int dm_test_fdt_pre_reloc(struct unit_test_state *uts) * one with "bootph-all" property (a-test node), and the other * one whose driver marked with DM_FLAG_PRE_RELOC flag (h-test node). */ - ut_asserteq(2, list_count_items(&uc->dev_head)); + ut_asserteq(2, list_count_nodes(&uc->dev_head)); return 0; } |