efi: disentangle the generic EFI stub from FDT
Subsystems (5)
Ard Biesheuvel
maintainercover efi: disentangle the generic EFI stub from FDT
EFI architectures other than x86 rely on FDT to pass information between the stub and the core kernel. In hindsight, this is probably a mistake, given the issues around abuse of the internal ABI, and potential inconsistencies between two sources of information that both originate in the firmware (memory map, command line, etc)
Another reason for avoiding updates to the DT is the fact that it interferes with secure boot and measured boot. Even if we measure the original firmware provided DT into the TPM, the DT that the kernel receives is a completely different blob, and verifying it against the TPM event log is currently impossible.
So let's start hacking away at this, and refactor the generic stub so that all the FDT pieces are isolated in a singe source file, and rely on generic EFI config tables for passing the initrd base and size. Ultimately, this should permit all EFI architectures doing DT boot to perform the handover to the core kernel in a different way, and pass on the firmware provided DT unmodified, but this requires some future work for ARM/arm64 and RISC-V.
However, we can easily convert the newly added LoongArch code to adopt this approach, and to consume the DT strictly for hardware descriptions (if not doing ACPI boot), and pass the initrd, memory map and everything else via EFI config tables. Generating empty DTBs on ACPI platforms will no longer be needed.
The first six patches as well as patch #10 are general cleanup, and can be merged separately. The remaining patches refactor the FDT code in the EFI stub so that we can avoid it on platforms that don't need it for other reasons. Finally, LoongArch is updated to use DT only for hardware descriptions when doing EFI boot.
Ard Biesheuvel (12):
efi: libstub: drop pointless get_memory_map() call efi/arm: libstub: move ARM specific code out of generic routines
efi: libstub: fix up the last remaining open coded boot service call
efi: libstub: fix type confusion for load_options_size
efi: libstub: avoid efi_get_memory_map() for allocating the virt map
efi: libstub: simplify efi_get_memory_map() and struct efi_boot_memmap
efi: libstub: unify initrd loading between architectures
efi: libstub: remove DT dependency from generic stub
efi: libstub: install boot-time memory map as config table
efi: libstub: remove pointless goto kludge
efi/loongarch: libstub: remove dependency on flattened DT
efi: loongarch: add support for DT hardware descriptions
Documentation/arm/uefi.rst | 4 - arch/arm/include/asm/efi.h | 3 +- arch/arm/kernel/efi.c | 79 +++++++++ arch/arm/kernel/setup.c | 2 +- arch/loongarch/Kconfig | 1 - arch/loongarch/include/asm/bootinfo.h | 2 +- arch/loongarch/kernel/efi.c | 44 ++++- arch/loongarch/kernel/env.c | 24 +-- arch/loongarch/kernel/head.S | 2 + arch/loongarch/kernel/setup.c | 4 +- drivers/firmware/efi/efi-init.c | 61 +------ drivers/firmware/efi/efi.c | 15 ++ drivers/firmware/efi/libstub/Makefile | 13 +- drivers/firmware/efi/libstub/arm64-stub.c | 19 +-- drivers/firmware/efi/libstub/efi-stub-helper.c | 127 +++++++------- drivers/firmware/efi/libstub/efi-stub.c | 94 ++++------- drivers/firmware/efi/libstub/efistub.h | 32 +--- drivers/firmware/efi/libstub/fdt.c | 175 +++++++++++--------- drivers/firmware/efi/libstub/loongarch-stub.c | 56 ++++++- drivers/firmware/efi/libstub/mem.c | 85 +++++----- drivers/firmware/efi/libstub/randomalloc.c | 25 +-- drivers/firmware/efi/libstub/relocate.c | 21 +-- drivers/firmware/efi/libstub/x86-stub.c | 30 +--- include/linux/efi.h | 15 ++ 24 files changed, 492 insertions(+), 441 deletions(-)
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 1/12 efi: libstub: drop pointless get_memory_map() call
Currently, the non-x86 stub code calls get_memory_map() redundantly, given that the data it returns is never used anywhere. So drop the call.
--- drivers/firmware/efi/libstub/fdt.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/firmware/efi/libstub/fdt.c +0 -8
@@ -280,14 +280,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, goto fail; } -/* -* Now that we have done our final memory allocation (and free) -* we can get the memory map key needed for exit_boot_services(). -*/ - status =efi_get_memory_map (&map); -if (status !=EFI_SUCCESS ) - goto fail_free_new_fdt; - status =update_fdt ((void *)fdt_addr, fdt_size, (void *)*new_fdt_addr,MAX_FDT_SIZE , cmdline_ptr, initrd_addr, initrd_size);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 2/12 efi/arm: libstub: move ARM specific code out of generic routines
In reply to Ard BiesheuvelMove some code that is only reachable when IS_ENABLED(CONFIG_ARM) into the ARM EFI arch code.
--- arch/arm/include/asm/efi.h | 3 +- arch/arm/kernel/efi.c | 79 ++++++++++++++++++++ arch/arm/kernel/setup.c | 2 +- drivers/firmware/efi/efi-init.c | 61 +-------------- 4 files changed, 84 insertions(+), 61 deletions(-)
arch/arm/include/asm/efi.h +2 -1
@@ -17,6 +17,7 @@#ifdef CONFIG_EFI void efi_init (void ); +void arm_efi_init (void );int efi_create_mapping (struct mm_struct *mm,efi_memory_desc_t *md);int efi_set_mapping_permissions (struct mm_struct *mm,efi_memory_desc_t *md);
@@ -37,7 +38,7 @@ void efi_virtmap_load(void);void efi_virtmap_unload (void );#else -#define efi_init () +#define arm_efi_init ()#endif /* CONFIG_EFI */ /* arch specific definitions used by the stub code */
arch/arm/kernel/efi.c +79 -0
88 lines not on this page · raw message
arch/arm/kernel/setup.c +1 -1
@@ -1141,7 +1141,7 @@ void __init setup_arch(char **cmdline_p)#endif setup_dma_zone (mdesc);xen_early_init (); -efi_init (); +arm_efi_init ();/* * Make sure the calculation for lowmem/highmem is set appropriately * before reserving/allocating any memory
drivers/firmware/efi/efi-init.c +2 -59
80 lines not on this page · raw message
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 3/12 efi: libstub: fix up the last remaining open coded boot service call
In reply to Ard BiesheuvelWe use a macro efi_bs_call() to call boot services, which is more concise, and on x86, it encapsulates the mixed mode handling. This code does not run in mixed mode, but let's switch to the macro for general tidiness.
--- drivers/firmware/efi/libstub/efi-stub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/efi/libstub/efi-stub.c +2 -2
@@ -160,8 +160,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,* information about the running image, such as size and the command * line. */ - status = efi_system_table->boottime->handle_protocol (handle, - &loaded_image_proto, (void *)&image); + status =efi_bs_call (handle_protocol, handle, &loaded_image_proto, + (void *)&image);if (status !=EFI_SUCCESS ) {efi_err ("Failed to get loaded image protocol\n" ); goto fail;
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 4/12 efi: libstub: fix type confusion for load_options_size
In reply to Ard BiesheuvelEven though it is unlikely to ever make a difference, let's use u32 consistently for the size of the load_options provided by the firmware (aka the command line)
While at it, do some general cleanup too: use efi_char16_t, avoid using options_chars in places where it really means options_size, etc.
--- drivers/firmware/efi/libstub/efi-stub-helper.c | 17 +++++++++-------- drivers/firmware/efi/libstub/efistub.h | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-)
drivers/firmware/efi/libstub/efi-stub-helper.c +9 -8
@@ -310,7 +310,7 @@ bool efi_load_option_unpack(efi_load_option_unpacked_t *dest,* * Detect this case and extract OptionalData. */ -void efi_apply_loadoptions_quirk (const void **load_options,int *load_options_size) +void efi_apply_loadoptions_quirk (const void **load_options,u32 *load_options_size) {const efi_load_option_t *load_option = *load_options;efi_load_option_unpacked_t load_option_unpacked;
@@ -341,21 +341,22 @@ void efi_apply_loadoptions_quirk(const void **load_options, int *load_options_si*/ char *efi_convert_cmdline (efi_loaded_image_t *image,int *cmd_line_len) { -const u16 *s2; -unsigned long cmdline_addr =0 ; -int options_chars =efi_table_attr (image, load_options_size); -const u16 *options =efi_table_attr (image, load_options); +const efi_char16_t *options =efi_table_attr (image, load_options); +u32 options_size =efi_table_attr (image, load_options_size);int options_bytes =0 , safe_options_bytes =0 ;/* UTF-8 bytes */ +unsigned long cmdline_addr =0 ; +const efi_char16_t *s2;bool in_quote = false;efi_status_t status; +u32 options_chars; -efi_apply_loadoptions_quirk ((const void **)&options, &options_chars); - options_chars /=sizeof (*options); +efi_apply_loadoptions_quirk ((const void **)&options, &options_size); + options_chars = options_size /sizeof (efi_char16_t);if (options) { s2 = options;while (options_bytes <COMMAND_LINE_SIZE && options_chars--) { -u16 c = *s2++; +efi_char16_t c = *s2++;if (c <0x80 ) {if (c ==L'\0' || c ==L'\n' )
drivers/firmware/efi/libstub/efistub.h +2 -2
@@ -861,7 +861,7 @@ typedef struct {u16 file_path_list_length;const efi_char16_t *description;const efi_device_path_protocol_t *file_path_list; -size_t optional_data_size; +u32 optional_data_size;const void *optional_data; } efi_load_option_unpacked_t;
@@ -906,7 +906,7 @@ __printf(1, 2) int efi_printk(char const *fmt, ...);void efi_free (unsigned long size,unsigned long addr); -void efi_apply_loadoptions_quirk (const void **load_options,int *load_options_size); +void efi_apply_loadoptions_quirk (const void **load_options,u32 *load_options_size);char *efi_convert_cmdline (efi_loaded_image_t *image,int *cmd_line_len);
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 5/12 efi: libstub: avoid efi_get_memory_map() for allocating the virt map
In reply to Ard BiesheuvelThe virt map is a set of efi_memory_desc_t descriptors that are passed to SetVirtualAddressMap() to inform the firmware about the desired virtual mapping of the regions marked as EFI_MEMORY_RUNTIME. The only reason we currently call the efi_get_memory_map() helper is that it gives us an allocation that is guaranteed to be of sufficient size. However, efi_get_memory_map() has grown some additional complexity over the years, and today, we're actually better off calling the EFI boot service directly with a zero size, which tells us how much memory should be enough for the virt map.
--- drivers/firmware/efi/libstub/efi-stub.c | 31 ++++++++++++++++++++ drivers/firmware/efi/libstub/efistub.h | 2 ++ drivers/firmware/efi/libstub/fdt.c | 27 +++++------------ 3 files changed, 41 insertions(+), 19 deletions(-)
drivers/firmware/efi/libstub/efi-stub.c +31 -0
@@ -319,6 +319,35 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,return status; } +/* +* efi_allocate_virtmap() - create a pool allocation for the virtmap +* +* Create an allocation that is of sufficient size to hold all the memory +* descriptors that will be passed to SetVirtualAddressMap() to inform the +* firmware about the virtual mapping that will be used under the OS to call +* into the firmware. +*/ +efi_status_t efi_alloc_virtmap (efi_memory_desc_t **virtmap, +unsigned long *desc_size,u32 *desc_ver) +{ +unsigned long size, mmap_key; +efi_status_t status; + +/* +* Use the size of the current memory map as an upper bound for the +* size of the buffer we need to pass to SetVirtualAddressMap() to +* cover all EFI_MEMORY_RUNTIME regions. +*/ + size =0 ; + status =efi_bs_call (get_memory_map, &size,NULL , &mmap_key, desc_size, + desc_ver); +if (status !=EFI_BUFFER_TOO_SMALL ) +return EFI_LOAD_ERROR ; + +return efi_bs_call (allocate_pool,EFI_LOADER_DATA , size, + (void **)virtmap); +} +/* * efi_get_virtmap() - create a virtual mapping for the EFI memory map *
@@ -334,6 +363,8 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,efi_memory_desc_t *in, *out = runtime_map;int l; + *count =0 ; +for (l =0 ; l < map_size; l += desc_size) {u64 paddr, size;
drivers/firmware/efi/libstub/efistub.h +2 -0
@@ -885,6 +885,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,void *get_fdt (unsigned long *fdt_size); +efi_status_t efi_alloc_virtmap (efi_memory_desc_t **virtmap, +unsigned long *desc_size,u32 *desc_ver);void efi_get_virtmap (efi_memory_desc_t *memory_map,unsigned long map_size,unsigned long desc_size,efi_memory_desc_t *runtime_map,int *count);
drivers/firmware/efi/libstub/fdt.c +8 -19
@@ -199,7 +199,7 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)struct exit_boot_struct {efi_memory_desc_t *runtime_map; -int *runtime_entry_count; +int runtime_entry_count;void *new_fdt_addr; };
@@ -213,7 +213,7 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,* entries so that we can pass it straight to SetVirtualAddressMap() */ efi_get_virtmap (*map->map, *map->map_size, *map->desc_size, - p->runtime_map, p->runtime_entry_count); + p->runtime_map, &p->runtime_entry_count);return update_fdt_memmap (p->new_fdt_addr, map); }
@@ -246,26 +246,18 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,unsigned long map_size, desc_size, buff_size;u32 desc_ver;unsigned long mmap_key; -efi_memory_desc_t *memory_map, *runtime_map; +efi_memory_desc_t *memory_map;efi_status_t status; -int runtime_entry_count;struct efi_boot_memmap map;struct exit_boot_struct priv; - map.map = &runtime_map; map.map_size = &map_size; map.desc_size = &desc_size; map.desc_ver = &desc_ver; map.key_ptr = &mmap_key; map.buff_size = &buff_size; -/* -* Get a copy of the current memory map that we will use to prepare -* the input for SetVirtualAddressMap(). We don't have to worry about -* subsequent allocations adding entries, since they could not affect -* the number of EFI_MEMORY_RUNTIME regions. -*/ - status =efi_get_memory_map (&map); + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver);if (status !=EFI_SUCCESS ) {efi_err ("Unable to retrieve UEFI memory map.\n" );return status;
@@ -289,10 +281,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, goto fail_free_new_fdt; } - runtime_entry_count =0 ; - priv.runtime_map = runtime_map; - priv.runtime_entry_count = &runtime_entry_count; - priv.new_fdt_addr = (void *)*new_fdt_addr; + priv.new_fdt_addr = (void *)*new_fdt_addr; status =efi_exit_boot_services (handle, &map, &priv, exit_boot_func);
@@ -304,8 +293,8 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,/* Install the new virtual address map */ svam = efi_system_table->runtime->set_virtual_address_map; - status =svam (runtime_entry_count * desc_size, desc_size, - desc_ver, runtime_map); + status =svam (priv.runtime_entry_count * desc_size, desc_size, + desc_ver, priv.runtime_map);/* * We are beyond the point of no return here, so if the call to
@@ -337,7 +326,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,efi_free (MAX_FDT_SIZE , *new_fdt_addr); fail: - efi_system_table->boottime->free_pool (runtime_map); +efi_bs_call (free_pool, priv.runtime_map);return EFI_LOAD_ERROR ; }
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 6/12 efi: libstub: simplify efi_get_memory_map() and struct efi_boot_memmap
In reply to Ard BiesheuvelCurrently, struct efi_boot_memmap is a struct that is passed around between callers of efi_get_memory_map() and the users of the resulting data, and which carries pointers to various variables whose values are provided by the EFI GetMemoryMap() boot service.
This is overly complex, and it is much easier to carry these values in the struct itself. So turn the struct into one that carries these data items directly, including a flex array for the variable number of EFI memory descriptors that the boot service may return.
--- drivers/firmware/efi/libstub/arm64-stub.c | 17 ++--- drivers/firmware/efi/libstub/efi-stub-helper.c | 26 ++++---- drivers/firmware/efi/libstub/efistub.h | 15 +---- drivers/firmware/efi/libstub/fdt.c | 37 +++++------ drivers/firmware/efi/libstub/mem.c | 65 ++++++-------------- drivers/firmware/efi/libstub/randomalloc.c | 23 +++---- drivers/firmware/efi/libstub/relocate.c | 21 ++----- drivers/firmware/efi/libstub/x86-stub.c | 20 ++---- include/linux/efi.h | 9 +++ 9 files changed, 80 insertions(+), 153 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +4 -13
@@ -50,26 +50,17 @@ efi_status_t check_platform_features(void)*/ static bool check_image_region (u64 base,u64 size) { -unsigned long map_size, desc_size, buff_size; -efi_memory_desc_t *memory_map; -struct efi_boot_memmap map; +struct efi_boot_memmap *map;efi_status_t status;bool ret = false;int map_offset; - map.map = &memory_map; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver =NULL ; - map.key_ptr =NULL ; - map.buff_size = &buff_size; - status =efi_get_memory_map (&map);if (status !=EFI_SUCCESS )return false; -for (map_offset =0 ; map_offset < map_size; map_offset += desc_size) { -efi_memory_desc_t *md = (void *)memory_map + map_offset; +for (map_offset =0 ; map_offset < map->map_size; map_offset += map->desc_size) { +efi_memory_desc_t *md = (void *)map->map + map_offset;u64 end = md->phys_addr + md->num_pages *EFI_PAGE_SIZE ;/*
@@ -82,7 +73,7 @@ static bool check_image_region(u64 base, u64 size) } } -efi_bs_call (free_pool, memory_map); +efi_bs_call (free_pool, map);return ret; }
drivers/firmware/efi/libstub/efi-stub-helper.c +12 -14
@@ -420,7 +420,6 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)/** * efi_exit_boot_services() - Exit boot services * @handle: handle of the exiting image -* @map: pointer to receive the memory map * @priv: argument to be passed to @priv_func * @priv_func: function to process the memory map before exiting boot services *
@@ -433,14 +432,13 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)* * Return: status code */ -efi_status_t efi_exit_boot_services (void *handle, -struct efi_boot_memmap *map, -void *priv, +efi_status_t efi_exit_boot_services (void *handle,void *priv,efi_exit_boot_map_processing priv_func) { +struct efi_boot_memmap *map;efi_status_t status; - status =efi_get_memory_map (map); + status =efi_get_memory_map (&map);if (status !=EFI_SUCCESS ) goto fail;
@@ -452,7 +450,7 @@ efi_status_t efi_exit_boot_services(void *handle,if (efi_disable_pci_dma)efi_pci_disable_bridge_busmaster (); - status =efi_bs_call (exit_boot_services, handle, *map->key_ptr); + status =efi_bs_call (exit_boot_services, handle, map->map_key);if (status ==EFI_INVALID_PARAMETER ) {/*
@@ -468,13 +466,13 @@ efi_status_t efi_exit_boot_services(void *handle,* buffer should account for any changes in the map so the call * to get_memory_map() is expected to succeed here. */ - *map->map_size = *map->buff_size; + map->map_size = map->buff_size; status =efi_bs_call (get_memory_map, - map->map_size, - *map->map, - map->key_ptr, - map->desc_size, - map->desc_ver); + &map->map_size, + &map->map, + &map->map_key, + &map->desc_size, + &map->desc_ver);/* exit_boot_services() was called, thus cannot free */ if (status !=EFI_SUCCESS )
@@ -485,7 +483,7 @@ efi_status_t efi_exit_boot_services(void *handle,if (status !=EFI_SUCCESS ) goto fail; - status =efi_bs_call (exit_boot_services, handle, *map->key_ptr); + status =efi_bs_call (exit_boot_services, handle, map->map_key); }/* exit_boot_services() was called, thus cannot free */
@@ -495,7 +493,7 @@ efi_status_t efi_exit_boot_services(void *handle,return EFI_SUCCESS ; free_map: -efi_bs_call (free_pool, *map->map); +efi_bs_call (free_pool, map); fail:return status; }
drivers/firmware/efi/libstub/efistub.h +2 -13
@@ -160,15 +160,6 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)*/ #define EFI_MMAP_NR_SLACK_SLOTS 8 -struct efi_boot_memmap { -efi_memory_desc_t **map; -unsigned long *map_size; -unsigned long *desc_size; -u32 *desc_ver; -unsigned long *key_ptr; -unsigned long *buff_size; -}; -typedef struct efi_generic_dev_path efi_device_path_protocol_t ;union efi_device_path_to_text_protocol {
@@ -871,9 +862,7 @@ typedef efi_status_t (*efi_exit_boot_map_processing)(struct efi_boot_memmap *map, void *priv); -efi_status_t efi_exit_boot_services (void *handle, -struct efi_boot_memmap *map, -void *priv, +efi_status_t efi_exit_boot_services (void *handle,void *priv,efi_exit_boot_map_processing priv_func); efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
@@ -912,7 +901,7 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_sichar *efi_convert_cmdline (efi_loaded_image_t *image,int *cmd_line_len); -efi_status_t efi_get_memory_map (struct efi_boot_memmap *map); +efi_status_t efi_get_memory_map (struct efi_boot_memmap **map);efi_status_t efi_allocate_pages (unsigned long size,unsigned long *addr,unsigned long max);
drivers/firmware/efi/libstub/fdt.c +16 -21
@@ -170,25 +170,25 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)if (node <0 )return EFI_LOAD_ERROR ; - fdt_val64 =cpu_to_fdt64 ((unsigned long )*map->map); + fdt_val64 =cpu_to_fdt64 ((unsigned long )map->map); err =fdt_setprop_inplace_var (fdt, node,"linux,uefi-mmap-start" , fdt_val64);if (err)return EFI_LOAD_ERROR ; - fdt_val32 =cpu_to_fdt32 (*map->map_size); + fdt_val32 =cpu_to_fdt32 (map->map_size); err =fdt_setprop_inplace_var (fdt, node,"linux,uefi-mmap-size" , fdt_val32);if (err)return EFI_LOAD_ERROR ; - fdt_val32 =cpu_to_fdt32 (*map->desc_size); + fdt_val32 =cpu_to_fdt32 (map->desc_size); err =fdt_setprop_inplace_var (fdt, node,"linux,uefi-mmap-desc-size" , fdt_val32);if (err)return EFI_LOAD_ERROR ; - fdt_val32 =cpu_to_fdt32 (*map->desc_ver); + fdt_val32 =cpu_to_fdt32 (map->desc_ver); err =fdt_setprop_inplace_var (fdt, node,"linux,uefi-mmap-desc-ver" , fdt_val32);if (err)
@@ -198,21 +198,24 @@ static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map) }struct exit_boot_struct { +struct efi_boot_memmap *boot_memmap;efi_memory_desc_t *runtime_map;int runtime_entry_count;void *new_fdt_addr; }; -static efi_status_t exit_boot_func (struct efi_boot_memmap *map, -void *priv) +static efi_status_t exit_boot_func (struct efi_boot_memmap *map,void *priv) {struct exit_boot_struct *p = priv; + + p->boot_memmap = map; +/* * Update the memory map with virtual addresses. The function will also * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME * entries so that we can pass it straight to SetVirtualAddressMap() */ -efi_get_virtmap (*map->map, *map->map_size, *map->desc_size, +efi_get_virtmap (map->map, map->map_size, map->desc_size, p->runtime_map, &p->runtime_entry_count);return update_fdt_memmap (p->new_fdt_addr, map);
@@ -243,20 +246,11 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, unsigned long fdt_addr, unsigned long fdt_size) { -unsigned long map_size, desc_size, buff_size; +unsigned long desc_size;u32 desc_ver; -unsigned long mmap_key; -efi_memory_desc_t *memory_map;efi_status_t status; -struct efi_boot_memmap map;struct exit_boot_struct priv; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver = &desc_ver; - map.key_ptr = &mmap_key; - map.buff_size = &buff_size; - status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver);if (status !=EFI_SUCCESS ) {efi_err ("Unable to retrieve UEFI memory map.\n" );
@@ -265,7 +259,6 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,efi_info ("Exiting boot services...\n" ); - map.map = &memory_map; status =efi_allocate_pages (MAX_FDT_SIZE , new_fdt_addr,ULONG_MAX );if (status !=EFI_SUCCESS ) {efi_err ("Unable to allocate memory for new device tree.\n" );
@@ -283,7 +276,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, priv.new_fdt_addr = (void *)*new_fdt_addr; - status =efi_exit_boot_services (handle, &map, &priv, exit_boot_func); + status =efi_exit_boot_services (handle, &priv, exit_boot_func);if (status ==EFI_SUCCESS ) {efi_set_virtual_address_map_t *svam;
@@ -302,6 +295,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,* incoming kernel but proceed normally otherwise. */ if (status !=EFI_SUCCESS ) { +efi_memory_desc_t *p;int l;/*
@@ -310,8 +304,9 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,* the incoming kernel that no virtual translation has * been installed. */ -for (l =0 ; l < map_size; l += desc_size) { -efi_memory_desc_t *p = (void *)memory_map + l; +for (l =0 ; l < priv.boot_memmap->map_size; + l += priv.boot_memmap->desc_size) { + p = (void *)priv.boot_memmap->map + l;if (p->attribute &EFI_MEMORY_RUNTIME ) p->virt_addr =0 ;
drivers/firmware/efi/libstub/mem.c +19 -46
90 lines not on this page · raw message
drivers/firmware/efi/libstub/randomalloc.c +7 -16
@@ -55,20 +55,11 @@ efi_status_t efi_random_alloc(unsigned long size,unsigned long *addr, unsigned long random_seed) { - unsigned long map_size, desc_size, total_slots = 0, target_slot; + unsigned long total_slots = 0, target_slot;unsigned long total_mirrored_slots =0 ; -unsigned long buff_size; +struct efi_boot_memmap *map;efi_status_t status; -efi_memory_desc_t *memory_map;int map_offset; -struct efi_boot_memmap map; - - map.map = &memory_map; - map.map_size = &map_size; - map.desc_size = &desc_size; - map.desc_ver =NULL ; - map.key_ptr =NULL ; - map.buff_size = &buff_size; status =efi_get_memory_map (&map);if (status !=EFI_SUCCESS )
@@ -80,8 +71,8 @@ efi_status_t efi_random_alloc(unsigned long size, size =round_up (size,EFI_ALLOC_ALIGN );/* count the suitable slots in each memory map entry */ -for (map_offset =0 ; map_offset < map_size; map_offset += desc_size) { -efi_memory_desc_t *md = (void *)memory_map + map_offset; +for (map_offset =0 ; map_offset < map->map_size; map_offset += map->desc_size) { +efi_memory_desc_t *md = (void *)map->map + map_offset;unsigned long slots; slots =get_entry_num_slots (md, size,ilog2 (align));
@@ -109,8 +100,8 @@ efi_status_t efi_random_alloc(unsigned long size,* to calculate the randomly chosen address, and allocate it directly * using EFI_ALLOCATE_ADDRESS. */ -for (map_offset =0 ; map_offset < map_size; map_offset += desc_size) { -efi_memory_desc_t *md = (void *)memory_map + map_offset; +for (map_offset =0 ; map_offset < map->map_size; map_offset += map->desc_size) { +efi_memory_desc_t *md = (void *)map->map + map_offset;efi_physical_addr_t target;unsigned long pages;
@@ -133,7 +124,7 @@ efi_status_t efi_random_alloc(unsigned long size,break ; } -efi_bs_call (free_pool, memory_map); +efi_bs_call (free_pool, map);return status; }
drivers/firmware/efi/libstub/relocate.c +6 -15
@@ -23,21 +23,12 @@efi_status_t efi_low_alloc_above (unsigned long size,unsigned long align,unsigned long *addr,unsigned long min) { -unsigned long map_size, desc_size, buff_size; -efi_memory_desc_t *map; +struct efi_boot_memmap *map;efi_status_t status;unsigned long nr_pages;int i; -struct efi_boot_memmap boot_map; - boot_map.map = ↦ - boot_map.map_size = &map_size; - boot_map.desc_size = &desc_size; - boot_map.desc_ver =NULL ; - boot_map.key_ptr =NULL ; - boot_map.buff_size = &buff_size; - - status =efi_get_memory_map (&boot_map); + status =efi_get_memory_map (&map);if (status !=EFI_SUCCESS ) goto fail;
@@ -52,12 +43,12 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, size =round_up (size,EFI_ALLOC_ALIGN ); nr_pages = size /EFI_PAGE_SIZE ; -for (i =0 ; i < map_size / desc_size; i++) { +for (i =0 ; i < map->map_size / map->desc_size; i++) {efi_memory_desc_t *desc; -unsigned long m = (unsigned long )map; +unsigned long m = (unsigned long )map->map;u64 start, end; - desc =efi_early_memdesc_ptr (m, desc_size, i); + desc =efi_early_memdesc_ptr (m, map->desc_size, i);if (desc->type !=EFI_CONVENTIONAL_MEMORY )continue ;
@@ -87,7 +78,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align, } } -if (i == map_size / desc_size) +if (i == map->map_size / map->desc_size) status =EFI_NOT_FOUND ;efi_bs_call (free_pool, map);
drivers/firmware/efi/libstub/x86-stub.c +5 -15
@@ -716,32 +716,22 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,efi_set_u64_split ((unsigned long )efi_system_table, &p->efi->efi_systab, &p->efi->efi_systab_hi); - p->efi->efi_memdesc_size = *map->desc_size; - p->efi->efi_memdesc_version = *map->desc_ver; -efi_set_u64_split ((unsigned long )*map->map, + p->efi->efi_memdesc_size = map->desc_size; + p->efi->efi_memdesc_version = map->desc_ver; +efi_set_u64_split ((unsigned long )map->map, &p->efi->efi_memmap, &p->efi->efi_memmap_hi); - p->efi->efi_memmap_size = *map->map_size; + p->efi->efi_memmap_size = map->map_size;return EFI_SUCCESS ; }static efi_status_t exit_boot (struct boot_params *boot_params,void *handle) { -unsigned long map_sz, key, desc_size, buff_size; -efi_memory_desc_t *mem_map;struct setup_data *e820ext =NULL ;__u32 e820ext_size =0 ;efi_status_t status; -__u32 desc_version; -struct efi_boot_memmap map;struct exit_boot_struct priv; - map.map = &mem_map; - map.map_size = &map_sz; - map.desc_size = &desc_size; - map.desc_ver = &desc_version; - map.key_ptr = &key; - map.buff_size = &buff_size; priv.boot_params = boot_params; priv.efi = &boot_params->efi_info;
@@ -750,7 +740,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)return status;/* Might as well exit boot services now */ - status =efi_exit_boot_services (handle, &map, &priv, exit_boot_func); + status =efi_exit_boot_services (handle, &priv, exit_boot_func);if (status !=EFI_SUCCESS )return status;
include/linux/efi.h +9 -0
@@ -522,6 +522,15 @@ typedef union {efi_system_table_32_t mixed_mode; } efi_system_table_t; +struct efi_boot_memmap { +unsigned long map_size; +unsigned long desc_size; +u32 desc_ver; +unsigned long map_key; +unsigned long buff_size; +efi_memory_desc_t map[]; +}; +/* * Architecture independent structure for describing a memory map for the * benefit of efi_memmap_init_early(), and for passing context between
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 7/12 efi: libstub: unify initrd loading between architectures
In reply to Ard BiesheuvelUse a EFI configuration table to pass the initrd to the core kernel, instead of per-arch methods. This cleans up the code considerably, and should make it easier for architectures to get rid of their reliance on DT for doing EFI boot in the future.
--- Documentation/arm/uefi.rst | 4 -- drivers/firmware/efi/efi.c | 15 +++++ drivers/firmware/efi/libstub/efi-stub-helper.c | 64 ++++++++++---------- drivers/firmware/efi/libstub/efi-stub.c | 14 ++--- drivers/firmware/efi/libstub/efistub.h | 3 - drivers/firmware/efi/libstub/fdt.c | 41 +++---------- drivers/firmware/efi/libstub/x86-stub.c | 10 +-- include/linux/efi.h | 5 ++ 8 files changed, 67 insertions(+), 89 deletions(-)
Documentation/arm/uefi.rst +0 -4
@@ -65,10 +65,6 @@ linux,uefi-mmap-desc-size 32-bit Size in bytes of each entry in the UEFI linux,uefi-mmap-desc-ver 32-bit Version of the mmap descriptor format. -linux,initrd-start 64-bit Physical start address of an initrd - -linux,initrd-end 64-bit Physical end address of an initrd - kaslr-seed 64-bit Entropy used to randomize the kernel image base address location. ========================== ====== ===========================================
drivers/firmware/efi/efi.c +15 -0
@@ -21,6 +21,7 @@#include <linux/device.h> #include <linux/efi.h> #include <linux/of.h> +#include <linux/initrd.h> #include <linux/io.h> #include <linux/kexec.h> #include <linux/platform_device.h>
@@ -55,6 +56,7 @@ EXPORT_SYMBOL(efi);unsigned long __ro_after_init efi_rng_seed =EFI_INVALID_TABLE_ADDR ;static unsigned long __initdata mem_reserve =EFI_INVALID_TABLE_ADDR ;static unsigned long __initdata rt_prop =EFI_INVALID_TABLE_ADDR ; +static unsigned long __initdata initrd =EFI_INVALID_TABLE_ADDR ;struct mm_struct efi_mm = { .mm_rb =RB_ROOT ,
@@ -532,6 +534,7 @@ static const efi_config_table_type_t common_tables[] __initconst = { {LINUX_EFI_TPM_EVENT_LOG_GUID, &efi.tpm_log, "TPMEventLog" }, {LINUX_EFI_TPM_FINAL_LOG_GUID, &efi.tpm_final_log, "TPMFinalLog" }, {LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" }, + {LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" }, {EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" }, #ifdef CONFIG_EFI_RCI2_TABLE {DELLEMC_EFI_RCI2_TABLE_GUID, &rci2_table_phys },
@@ -674,6 +677,18 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, } } +if (IS_ENABLED (CONFIG_BLK_DEV_INITRD ) && + initrd !=EFI_INVALID_TABLE_ADDR ) { +struct linux_efi_initrd *tbl; + + tbl =early_memremap (initrd,sizeof (*tbl)); +if (tbl) { + phys_initrd_start = tbl->base; + phys_initrd_size = tbl->size; +early_memunmap (tbl,sizeof (*tbl)); + } + } +return 0 ; }
drivers/firmware/efi/libstub/efi-stub-helper.c +31 -33
141 lines not on this page · raw message
drivers/firmware/efi/libstub/efi-stub.c +5 -9
@@ -130,8 +130,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,unsigned long image_addr;unsigned long image_size =0 ;/* addr/point and size pairs for memory management*/ -unsigned long initrd_addr =0 ; -unsigned long initrd_size =0 ;unsigned long fdt_addr =0 ;/* Original DTB */ unsigned long fdt_size =0 ;char *cmdline_ptr =NULL ;
@@ -247,7 +245,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,if (!fdt_addr)efi_info ("Generating empty DTB\n" ); -efi_load_initrd (image, &initrd_addr, &initrd_size,ULONG_MAX , +efi_load_initrd (image,ULONG_MAX ,efi_get_max_initrd_addr (image_addr));efi_random_get_seed ();
@@ -290,11 +288,10 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,install_memreserve_table (); - status =allocate_new_fdt_and_exit_boot (handle, &fdt_addr, - initrd_addr, initrd_size, - cmdline_ptr, fdt_addr, fdt_size); + status =allocate_new_fdt_and_exit_boot (handle, &fdt_addr, cmdline_ptr, + fdt_addr, fdt_size);if (status !=EFI_SUCCESS ) - goto fail_free_initrd; + goto fail_free_fdt;if (IS_ENABLED (CONFIG_ARM ))efi_handle_post_ebs_state ();
@@ -302,10 +299,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,efi_enter_kernel (image_addr, fdt_addr,fdt_totalsize ((void *)fdt_addr));/* not reached */ -fail_free_initrd: +fail_free_fdt:efi_err ("Failed to update FDT and exit boot services\n" ); -efi_free (initrd_size, initrd_addr);efi_free (fdt_size, fdt_addr); fail_free_image:
drivers/firmware/efi/libstub/efistub.h +0 -3
@@ -867,7 +867,6 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,efi_status_t allocate_new_fdt_and_exit_boot (void *handle,unsigned long *new_fdt_addr, -u64 initrd_addr,u64 initrd_size,char *cmdline_ptr,unsigned long fdt_addr,unsigned long fdt_size);
@@ -944,8 +943,6 @@ static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image, }efi_status_t efi_load_initrd (efi_loaded_image_t *image, -unsigned long *load_addr, -unsigned long *load_size,unsigned long soft_limit,unsigned long hard_limit);/*
drivers/firmware/efi/libstub/fdt.c +10 -31
69 lines not on this page · raw message
drivers/firmware/efi/libstub/x86-stub.c +1 -9
@@ -766,7 +766,6 @@ unsigned long efi_main(efi_handle_t handle,unsigned long bzimage_addr = (unsigned long )startup_32;unsigned long buffer_start, buffer_end;struct setup_header *hdr = &boot_params->hdr; -unsigned long addr, size;efi_status_t status; efi_system_table = sys_table_arg;
@@ -861,16 +860,9 @@ unsigned long efi_main(efi_handle_t handle,* arguments will be processed only if image is not NULL, which will be * the case only if we were loaded via the PE entry point. */ - status =efi_load_initrd (image, &addr, &size, hdr->initrd_addr_max, -ULONG_MAX ); + status =efi_load_initrd (image, hdr->initrd_addr_max,ULONG_MAX );if (status !=EFI_SUCCESS ) goto fail; -if (size >0 ) { -efi_set_u64_split (addr, &hdr->ramdisk_image, - &boot_params->ext_ramdisk_image); -efi_set_u64_split (size, &hdr->ramdisk_size, - &boot_params->ext_ramdisk_size); - }/* * If the boot loader gave us a value for secure_boot then we use that,
include/linux/efi.h +5 -0
@@ -1343,6 +1343,11 @@ struct linux_efi_coco_secret_area {u64 size; }; +struct linux_efi_initrd { +unsigned long base; +unsigned long size; +}; +/* Header of a populated EFI secret area */ #define EFI_SECRET_TABLE_HEADER_GUID EFI_GUID(0x1e74f542, 0x71dd, 0x4d66, 0x96, 0x3e, 0xef, 0x42, 0x87, 0xff, 0x17, 0x3b)
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 8/12 efi: libstub: remove DT dependency from generic stub
In reply to Ard BiesheuvelRefactor the generic EFI stub entry code so that all the dependencies on device tree are abstracted and hidden behind a generic efi_boot_kernel() routine that can also be implemented in other ways. This allows users of the generic stub to avoid using FDT for passing information to the core kernel.
--- drivers/firmware/efi/libstub/efi-stub.c | 53 +--------------- drivers/firmware/efi/libstub/efistub.h | 7 +-- drivers/firmware/efi/libstub/fdt.c | 64 ++++++++++++++++++-- 3 files changed, 63 insertions(+), 61 deletions(-)
drivers/firmware/efi/libstub/efi-stub.c +1 -52
@@ -10,7 +10,6 @@*/ #include <linux/efi.h> -#include <linux/libfdt.h> #include <asm/efi.h> #include "efistub.h"
@@ -130,14 +129,11 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,unsigned long image_addr;unsigned long image_size =0 ;/* addr/point and size pairs for memory management*/ -unsigned long fdt_addr =0 ;/* Original DTB */ -unsigned long fdt_size =0 ;char *cmdline_ptr =NULL ;int cmdline_size =0 ;efi_guid_t loaded_image_proto =LOADED_IMAGE_PROTOCOL_GUID ;unsigned long reserve_addr =0 ;unsigned long reserve_size =0 ; -enum efi_secureboot_mode secure_boot;struct screen_info *si;efi_properties_table_t *prop_tbl;
@@ -213,38 +209,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,/* Ask the firmware to clear memory on unclean shutdown */ efi_enable_reset_attack_mitigation (); - secure_boot =efi_get_secureboot (); - -/* -* Unauthenticated device tree data is a security hazard, so ignore -* 'dtb=' unless UEFI Secure Boot is disabled. We assume that secure -* boot is enabled if we can't determine its state. -*/ -if (!IS_ENABLED (CONFIG_EFI_ARMSTUB_DTB_LOADER ) || - secure_boot != efi_secureboot_mode_disabled) { -if (strstr (cmdline_ptr,"dtb=" )) -efi_err ("Ignoring DTB from command line.\n" ); - }else { - status =efi_load_dtb (image, &fdt_addr, &fdt_size); - -if (status !=EFI_SUCCESS ) { -efi_err ("Failed to load device tree!\n" ); - goto fail_free_image; - } - } - -if (fdt_addr) { -efi_info ("Using DTB from command line\n" ); - }else { -/* Look for a device tree configuration table entry. */ - fdt_addr = (uintptr_t )get_fdt (&fdt_size); -if (fdt_addr) -efi_info ("Using DTB from configuration table\n" ); - } - -if (!fdt_addr) -efi_info ("Generating empty DTB\n" ); -efi_load_initrd (image,ULONG_MAX ,efi_get_max_initrd_addr (image_addr));
@@ -288,23 +252,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,install_memreserve_table (); - status =allocate_new_fdt_and_exit_boot (handle, &fdt_addr, cmdline_ptr, - fdt_addr, fdt_size); -if (status !=EFI_SUCCESS ) - goto fail_free_fdt; - -if (IS_ENABLED (CONFIG_ARM )) -efi_handle_post_ebs_state (); - -efi_enter_kernel (image_addr, fdt_addr,fdt_totalsize ((void *)fdt_addr)); -/* not reached */ - -fail_free_fdt: -efi_err ("Failed to update FDT and exit boot services\n" ); - -efi_free (fdt_size, fdt_addr); + status =efi_boot_kernel (handle, image, image_addr, cmdline_ptr); -fail_free_image:efi_free (image_size, image_addr);efi_free (reserve_size, reserve_addr); fail_free_screeninfo:
drivers/firmware/efi/libstub/efistub.h +2 -5
@@ -865,11 +865,8 @@ typedef efi_status_t (*efi_exit_boot_map_processing)(efi_status_t efi_exit_boot_services (void *handle,void *priv,efi_exit_boot_map_processing priv_func); -efi_status_t allocate_new_fdt_and_exit_boot (void *handle, -unsigned long *new_fdt_addr, -char *cmdline_ptr, -unsigned long fdt_addr, -unsigned long fdt_size); +efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image, +unsigned long image_addr,char *cmdline_ptr);void *get_fdt (unsigned long *fdt_size);
drivers/firmware/efi/libstub/fdt.c +60 -4
94 lines not on this page · raw message
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 9/12 efi: libstub: install boot-time memory map as config table
In reply to Ard BiesheuvelExpose the EFI boot time memory map to the kernel via a configuration table. This is arch agnostic and enables future changes that remove the dependency on DT on architectures that don't otherwise rely on it.
--- drivers/firmware/efi/libstub/arm64-stub.c | 2 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 3 ++- drivers/firmware/efi/libstub/mem.c | 26 ++++++++++++++++++-- drivers/firmware/efi/libstub/randomalloc.c | 2 +- drivers/firmware/efi/libstub/relocate.c | 2 +- include/linux/efi.h | 1 + 7 files changed, 31 insertions(+), 7 deletions(-)
drivers/firmware/efi/libstub/arm64-stub.c +1 -1
@@ -55,7 +55,7 @@ static bool check_image_region(u64 base, u64 size)bool ret = false;int map_offset; - status =efi_get_memory_map (&map); + status =efi_get_memory_map (&map, false);if (status !=EFI_SUCCESS )return false;
drivers/firmware/efi/libstub/efi-stub-helper.c +1 -1
@@ -438,7 +438,7 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,struct efi_boot_memmap *map;efi_status_t status; - status =efi_get_memory_map (&map); + status =efi_get_memory_map (&map, true);if (status !=EFI_SUCCESS ) goto fail;
drivers/firmware/efi/libstub/efistub.h +2 -1
@@ -897,7 +897,8 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_sichar *efi_convert_cmdline (efi_loaded_image_t *image,int *cmd_line_len); -efi_status_t efi_get_memory_map (struct efi_boot_memmap **map); +efi_status_t efi_get_memory_map (struct efi_boot_memmap **map, +bool install_cfg_tbl);efi_status_t efi_allocate_pages (unsigned long size,unsigned long *addr,unsigned long max);
drivers/firmware/efi/libstub/mem.c +24 -2
@@ -9,14 +9,20 @@* efi_get_memory_map() - get memory map * @map: pointer to memory map pointer to which to assign the * newly allocated memory map +* @install_cfg_tbl: whether or not to install the boot memory map as a +* configuration table * * Retrieve the UEFI memory map. The allocated memory leaves room for * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries. * * Return: status code */ -efi_status_t efi_get_memory_map (struct efi_boot_memmap **map) +efi_status_t efi_get_memory_map (struct efi_boot_memmap **map, +bool install_cfg_tbl) { +int memtype = install_cfg_tbl ?EFI_ACPI_RECLAIM_MEMORY + :EFI_LOADER_DATA ; +efi_guid_t tbl_guid =LINUX_EFI_BOOT_MEMMAP_GUID ;struct efi_boot_memmap *m, tmp;efi_status_t status;unsigned long size;
@@ -28,11 +34,23 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)return EFI_LOAD_ERROR ; size = tmp.map_size + tmp.desc_size *EFI_MMAP_NR_SLACK_SLOTS ; - status =efi_bs_call (allocate_pool,EFI_LOADER_DATA ,sizeof (*m) + size, + status =efi_bs_call (allocate_pool, memtype,sizeof (*m) + size, (void **)&m);if (status !=EFI_SUCCESS )return status; +if (install_cfg_tbl) { +/* +* Installing a configuration table might allocate memory, and +* this may modify the memory map. This means we should install +* the configuration table first, and re-install or delete it +* as needed. +*/ + status =efi_bs_call (install_configuration_table, &tbl_guid, m); +if (status !=EFI_SUCCESS ) + goto free_map; + } + m->buff_size = m->map_size = size; status =efi_bs_call (get_memory_map, &m->map_size, m->map, &m->map_key, &m->desc_size, &m->desc_ver);
@@ -40,6 +58,10 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)if (status ==EFI_SUCCESS ) { *map = m; }else { +if (install_cfg_tbl) +efi_bs_call (install_configuration_table, &tbl_guid, +NULL ); +free_map:efi_bs_call (free_pool, m); }
drivers/firmware/efi/libstub/randomalloc.c +1 -1
@@ -61,7 +61,7 @@ efi_status_t efi_random_alloc(unsigned long size,efi_status_t status;int map_offset; - status =efi_get_memory_map (&map); + status =efi_get_memory_map (&map, false);if (status !=EFI_SUCCESS )return status;
drivers/firmware/efi/libstub/relocate.c +1 -1
@@ -28,7 +28,7 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,unsigned long nr_pages;int i; - status =efi_get_memory_map (&map); + status =efi_get_memory_map (&map, false);if (status !=EFI_SUCCESS ) goto fail;
include/linux/efi.h +1 -0
@@ -414,6 +414,7 @@ void efi_native_runtime_setup(void);#define LINUX_EFI_ZBOOT_MEDIA_GUID EFI_GUID(0xe565a30d, 0x47da, 0x4dbd, 0xb3, 0x54, 0x9b, 0xb5, 0xc8, 0x4f, 0x8b, 0xe2)#define LINUX_EFI_MOK_VARIABLE_TABLE_GUID EFI_GUID(0xc451ed2b, 0x9694, 0x45d3, 0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89)#define LINUX_EFI_COCO_SECRET_AREA_GUID EFI_GUID(0xadf956ad, 0xe98c, 0x484c, 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47) +#define LINUX_EFI_BOOT_MEMMAP_GUID EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)#define RISCV_EFI_BOOT_PROTOCOL_GUID EFI_GUID(0xccd15fec, 0x6f73, 0x4eec, 0x83, 0x95, 0x3e, 0x69, 0xe4, 0xb9, 0x40, 0xbf)
Signature · 1 line
2.35.1
Re: [PATCH 09/12] efi: libstub: install boot-time memory map as config table
Hi Ard,
Quoted 15 lines · Ard Biesheuvel
Expose the EFI boot time memory map to the kernel via a configuration table. This is arch agnostic and enables future changes that remove the dependency on DT on architectures that don't otherwise rely on it.
Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/libstub/arm64-stub.c | 2 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 3 ++- drivers/firmware/efi/libstub/mem.c | 26 ++++++++++++++++++-- drivers/firmware/efi/libstub/randomalloc.c | 2 +- drivers/firmware/efi/libstub/relocate.c | 2 +- include/linux/efi.h | 1 + 7 files changed, 31 insertions(+), 7 deletions(-)
[..]
Quoted 52 lines
drivers/firmware/efi/libstub/mem.c +20
-2@@ -9,14 +9,20 @@* efi_get_memory_map() - get memory map * @map: pointer to memory map pointer to which to assign the * newly allocated memory map +* @install_cfg_tbl: whether or not to install the boot memory map as a +* configuration table * * Retrieve the UEFI memory map. The allocated memory leaves room for * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries. * * Return: status code */ -efi_status_t efi_get_memory_map (struct efi_boot_memmap **map) +efi_status_t efi_get_memory_map (struct efi_boot_memmap **map, +bool install_cfg_tbl) { +int memtype = install_cfg_tbl ?EFI_ACPI_RECLAIM_MEMORY + :EFI_LOADER_DATA ; +efi_guid_t tbl_guid =LINUX_EFI_BOOT_MEMMAP_GUID ;struct efi_boot_memmap *m, tmp;efi_status_t status;unsigned long size;@@ -28,11 +34,23 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)return EFI_LOAD_ERROR ; size = tmp.map_size + tmp.desc_size *EFI_MMAP_NR_SLACK_SLOTS ; - status =efi_bs_call (allocate_pool,EFI_LOADER_DATA ,sizeof (*m) + size, + status =efi_bs_call (allocate_pool, memtype,sizeof (*m) + size, (void **)&m);if (status !=EFI_SUCCESS )return status; +if (install_cfg_tbl) { +/* +* Installing a configuration table might allocate memory, and +* this may modify the memory map. This means we should install +* the configuration table first, and re-install or delete it +* as needed. +*/ + status =efi_bs_call (install_configuration_table, &tbl_guid, m); +if (status !=EFI_SUCCESS ) + goto free_map; + } + m->buff_size = m->map_size = size; status =efi_bs_call (get_memory_map, &m->map_size, m->map, &m->map_key, &m->desc_size, &m->desc_ver);
drivers/firmware/efi/libstub/mem.c efi_status_t efi_get_memory_map(struct efi_boot_memmap **map) · line 66
Quoted 9 lines
drivers/firmware/efi/libstub/mem.c +4
-0@@ -40,6 +58,10 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)if (status ==EFI_SUCCESS ) { *map = m; }else { +if (install_cfg_tbl) +efi_bs_call (install_configuration_table, &tbl_guid, +NULL ); +free_map:efi_bs_call (free_pool, m); }
You have another commit about removing goto kludges, so maybe write this like the following, rather than a goto into an 'else' statement?
drivers/firmware/efi/libstub/mem.c +4 -2
@@ -64,10 +64,12 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) *map->key_ptr = key;if (map->desc_ver) *map->desc_ver = desc_version; - }else { -efi_bs_call (free_pool, m); } +free_map: +if (status !=EFI_SUCCESS ) +efi_bs_call (free_pool, m); + fail: *map->map = m;return status;
(This is a diff against next-20220920, not your branch, but you get the idea)
Thanks,
Joey
Ard Biesheuvel
maintainerRe: [PATCH 09/12] efi: libstub: install boot-time memory map as config table
Quoted 95 lines · Joey Gouly
Hi Ard,
Quoted 15 lines · Ard Biesheuvel
Expose the EFI boot time memory map to the kernel via a configuration table. This is arch agnostic and enables future changes that remove the dependency on DT on architectures that don't otherwise rely on it.
Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/libstub/arm64-stub.c | 2 +- drivers/firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/efistub.h | 3 ++- drivers/firmware/efi/libstub/mem.c | 26 ++++++++++++++++++-- drivers/firmware/efi/libstub/randomalloc.c | 2 +- drivers/firmware/efi/libstub/relocate.c | 2 +- include/linux/efi.h | 1 + 7 files changed, 31 insertions(+), 7 deletions(-)[..]
Quoted 52 lines
drivers/firmware/efi/libstub/mem.c +20
-2@@ -9,14 +9,20 @@* efi_get_memory_map() - get memory map * @map: pointer to memory map pointer to which to assign the * newly allocated memory map +* @install_cfg_tbl: whether or not to install the boot memory map as a +* configuration table * * Retrieve the UEFI memory map. The allocated memory leaves room for * up to EFI_MMAP_NR_SLACK_SLOTS additional memory map entries. * * Return: status code */ -efi_status_t efi_get_memory_map (struct efi_boot_memmap **map) +efi_status_t efi_get_memory_map (struct efi_boot_memmap **map, +bool install_cfg_tbl) { +int memtype = install_cfg_tbl ?EFI_ACPI_RECLAIM_MEMORY + :EFI_LOADER_DATA ; +efi_guid_t tbl_guid =LINUX_EFI_BOOT_MEMMAP_GUID ;struct efi_boot_memmap *m, tmp;efi_status_t status;unsigned long size;@@ -28,11 +34,23 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)return EFI_LOAD_ERROR ; size = tmp.map_size + tmp.desc_size *EFI_MMAP_NR_SLACK_SLOTS ; - status =efi_bs_call (allocate_pool,EFI_LOADER_DATA ,sizeof (*m) + size, + status =efi_bs_call (allocate_pool, memtype,sizeof (*m) + size, (void **)&m);if (status !=EFI_SUCCESS )return status; +if (install_cfg_tbl) { +/* +* Installing a configuration table might allocate memory, and +* this may modify the memory map. This means we should install +* the configuration table first, and re-install or delete it +* as needed. +*/ + status =efi_bs_call (install_configuration_table, &tbl_guid, m); +if (status !=EFI_SUCCESS ) + goto free_map; + } + m->buff_size = m->map_size = size; status =efi_bs_call (get_memory_map, &m->map_size, m->map, &m->map_key, &m->desc_size, &m->desc_ver);drivers/firmware/efi/libstub/mem.c efi_status_t efi_get_memory_map(struct efi_boot_memmap **map) · line 66
Quoted 9 lines
drivers/firmware/efi/libstub/mem.c +4
-0@@ -40,6 +58,10 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap **map)if (status ==EFI_SUCCESS ) { *map = m; }else { +if (install_cfg_tbl) +efi_bs_call (install_configuration_table, &tbl_guid, +NULL ); +free_map:efi_bs_call (free_pool, m); }You have another commit about removing goto kludges, so maybe write this like the following, rather than a goto into an 'else' statement?
drivers/firmware/efi/libstub/mem.c +0
-1@@ -64,10 +64,12 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) *map->key_ptr = key;if (map->desc_ver) *map->desc_ver = desc_version; - }else {
drivers/firmware/efi/libstub/mem.c efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) · line 75
Quoted 10 lines
drivers/firmware/efi/libstub/mem.c +4
-1-efi_bs_call (free_pool, m); } +free_map: +if (status !=EFI_SUCCESS ) +efi_bs_call (free_pool, m); + fail: *map->map = m;return status;
Yeah that might be better. Thanks for the suggestion.
Ard Biesheuvel
maintainerPATCH 10/12 efi: libstub: remove pointless goto kludge
In reply to Ard BiesheuvelRemove some goto cruft that serves no purpose and obfuscates the code.
--- drivers/firmware/efi/libstub/efi-stub-helper.c | 22 +++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-)
drivers/firmware/efi/libstub/efi-stub-helper.c +7 -15
@@ -439,13 +439,14 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,efi_status_t status; status =efi_get_memory_map (&map, true); -if (status !=EFI_SUCCESS ) - goto fail; +return status; status =priv_func (map, priv); -if (status !=EFI_SUCCESS ) - goto free_map; +if (status !=EFI_SUCCESS ) { +efi_bs_call (free_pool, map); +return status; + }if (efi_disable_pci_dma)efi_pci_disable_bridge_busmaster ();
@@ -476,25 +477,16 @@ efi_status_t efi_exit_boot_services(void *handle, void *priv,/* exit_boot_services() was called, thus cannot free */ if (status !=EFI_SUCCESS ) - goto fail; +return status; status =priv_func (map, priv);/* exit_boot_services() was called, thus cannot free */ if (status !=EFI_SUCCESS ) - goto fail; +return status; status =efi_bs_call (exit_boot_services, handle, map->map_key); } -/* exit_boot_services() was called, thus cannot free */ -if (status !=EFI_SUCCESS ) - goto fail; - -return EFI_SUCCESS ; - -free_map: -efi_bs_call (free_pool, map); -fail:return status; }
Signature · 1 line
2.35.1
Ard Biesheuvel
maintainerPATCH 11/12 efi/loongarch: libstub: remove dependency on flattened DT
In reply to Ard BiesheuvelLoongArch does not use FDT or DT natively [yet], and the only reason it currently uses it is so that it can reuse the existing EFI stub code.
Overloading the DT with data passed between the EFI stub and the core kernel has been a source of problems: there is the overlap between information provided by EFI which DT can also provide (initrd base/size, command line, memory descriptions), requiring us to reason about which is which and what to prioritize. It has also resulted in ABI leaks, i.e., internal ABI being promoted to external ABI inadvertently because the bootloader can set the EFI stub's DT properties as well (e.g., "kaslr-seed"). This has become especially problematic with boot environments that want to pretend that EFI boot is being done (to access ACPI and SMBIOS tables, for instance) but have no ability to execute the EFI stub, and so the environment that the EFI stub creates is emulated [poorly, in some cases].
Another downside of treating DT like this is that the DT binary that the kernel receives is different from the one created by the firmware, which is undesirable in the context of secure and measured boot.
Given that LoongArch support in Linux is brand new, we can avoid these pitfalls, and treat the DT strictly as a hardware description, and use a separate handover method between the EFI stub and the kernel. Now that initrd loading and passing the EFI memory map have been refactored into pure EFI routines that use EFI configuration tables, the only thing we need to pass directly is the kernel command line (even if we could pass this via a config table as well, it is used extremely early, so passing it directly is preferred in this case.)
--- arch/loongarch/Kconfig | 3 -- arch/loongarch/include/asm/bootinfo.h | 2 +- arch/loongarch/kernel/efi.c | 30 ++++++++++- arch/loongarch/kernel/env.c | 22 ++++---- arch/loongarch/kernel/head.S | 2 + arch/loongarch/kernel/setup.c | 4 +- drivers/firmware/efi/libstub/Makefile | 13 +++-- drivers/firmware/efi/libstub/loongarch-stub.c | 56 +++++++++++++++++--- 8 files changed, 100 insertions(+), 32 deletions(-)
arch/loongarch/Kconfig +0 -3
@@ -104,8 +104,6 @@ config LOONGARCH select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK - select OF - select OF_EARLY_FLATTREE select PCI select PCI_DOMAINS_GENERIC select PCI_ECAM if ACPI
@@ -311,7 +309,6 @@ config DMI config EFI bool "EFI runtime service support" select UCS2_STRING - select EFI_PARAMS_FROM_FDT select EFI_RUNTIME_WRAPPERS help This enables the kernel to use EFI runtime services that are
arch/loongarch/include/asm/bootinfo.h +1 -1
@@ -36,7 +36,7 @@ struct loongson_system_configuration { };extern u64 efi_system_table; -extern unsigned long fw_arg0, fw_arg1; +extern unsigned long fw_arg0, fw_arg1, fw_arg2;extern struct loongson_board_info b_info;extern struct loongson_system_configuration loongson_sysconf;
arch/loongarch/kernel/efi.c +29 -1
@@ -27,8 +27,13 @@static unsigned long efi_nr_tables;static unsigned long efi_config_table; +static unsigned long __initdata boot_memmap =EFI_INVALID_TABLE_ADDR ; +static efi_system_table_t *efi_systab; -static efi_config_table_type_t arch_tables[]__initdata = {{},}; +static efi_config_table_type_t arch_tables[]__initdata = { + {LINUX_EFI_BOOT_MEMMAP_GUID , &boot_memmap,"MEMMAP" }, + {}, +};void __init efi_runtime_init (void ) {
@@ -61,6 +66,8 @@ void __init efi_init(void)return ; } +efi_systab_report_header (&efi_systab->hdr, efi_systab->fw_vendor); +set_bit (EFI_64BIT , &efi.flags); efi_nr_tables = efi_systab->nr_tables; efi_config_table = (unsigned long )efi_systab->tables;
@@ -72,4 +79,25 @@ void __init efi_init(void)if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI )memblock_reserve (screen_info.lfb_base, screen_info.lfb_size); + +if (boot_memmap !=EFI_INVALID_TABLE_ADDR ) { +struct efi_memory_map_data data; +struct efi_boot_memmap *tbl; + + tbl =early_memremap_ro (boot_memmap,sizeof (*tbl)); +if (tbl) { + data.phys_map = boot_memmap +sizeof (*tbl); + data.size = tbl->map_size; + data.desc_size = tbl->desc_size; + data.desc_version = tbl->desc_ver; + +if (efi_memmap_init_early (&data) <0 ) +panic ("Unable to map EFI memory map.\n" ); + +memblock_reserve (data.phys_map &PAGE_MASK , +PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + +early_memunmap (tbl,sizeof (*tbl)); + } + } }
arch/loongarch/kernel/env.c +9 -13
@@ -8,7 +8,6 @@#include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> -#include <linux/of_fdt.h> #include <asm/early_ioremap.h> #include <asm/bootinfo.h> #include <asm/loongson.h>
@@ -20,21 +19,18 @@ EXPORT_SYMBOL(loongson_sysconf);void __init init_environ (void ) {int efi_boot = fw_arg0; -struct efi_memory_map_data data; -void *fdt_ptr =early_memremap_ro (fw_arg1,SZ_64K ); -if (efi_boot) -set_bit (EFI_BOOT , &efi.flags); -else -clear_bit (EFI_BOOT , &efi.flags); +if (efi_boot) { +char *cmdline =early_memremap_ro (fw_arg2,COMMAND_LINE_SIZE ); -early_init_dt_scan (fdt_ptr); -early_init_fdt_reserve_self (); - efi_system_table =efi_get_fdt_params (&data); +strscpy (boot_command_line, cmdline,COMMAND_LINE_SIZE ); +early_memunmap (cmdline,COMMAND_LINE_SIZE ); -efi_memmap_init_early (&data); -memblock_reserve (data.phys_map &PAGE_MASK , -PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + efi_system_table = fw_arg1; +set_bit (EFI_BOOT , &efi.flags); + }else { +clear_bit (EFI_BOOT , &efi.flags); + } }static int __init init_cpu_fullname (void )
arch/loongarch/kernel/head.S +2 -0
@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point st.d a0, t0, 0 # firmware arguments la t0, fw_arg1 st.d a1, t0, 0 + la t0, fw_arg2 + st.d a2, t0, 0 /* KSave3 used for percpu base, initialized as 0 */ csrwr zero, PERCPU_BASE_KS
arch/loongarch/kernel/setup.c +2 -2
@@ -51,7 +51,7 @@ struct screen_info screen_info __section(".data"); -unsigned long fw_arg0, fw_arg1; +unsigned long fw_arg0, fw_arg1, fw_arg2; DEFINE_PER_CPU(unsigned long, kernelsp);struct cpuinfo_loongarch cpu_data[NR_CPUS ]__read_mostly ;
@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);void __init platform_init (void ) { -efi_init ();#ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade ();#endif
@@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line;init_environ (); +efi_init ();memblock_init ();parse_early_param ();
drivers/firmware/efi/libstub/Makefile +8 -5
@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie -cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt +cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ -include $(srctree)/include/linux/hidden.h \
@@ -60,14 +60,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ alignedmem.o relocate.o vsprintf.o \ systable.o -# include the stub's generic dependencies from lib/ when building for ARM/arm64 -efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c +# include the stub's libfdt dependencies from lib/ when needed +libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \ + fdt_empty_tree.c fdt_sw.c + +lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \ + $(patsubst %.c,lib-%.o,$(libfdt-deps)) $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) -lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o intrinsics.o \ - $(patsubst %.c,lib-%.o,$(efi-deps-y)) +lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.o
drivers/firmware/efi/libstub/loongarch-stub.c +49 -7
75 lines not on this page · raw message
Signature · 1 line
2.35.1
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpi
The current way (so-called new world):
a0=efi boot flag, a1=fdt pointer
The new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdline
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method; 2, arm64, riscv and loongarch can use similar logics (light FDT); 3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
Huacai
Quoted 335 lines · Ard Biesheuvel
LoongArch does not use FDT or DT natively [yet], and the only reason it currently uses it is so that it can reuse the existing EFI stub code.
Overloading the DT with data passed between the EFI stub and the core kernel has been a source of problems: there is the overlap between information provided by EFI which DT can also provide (initrd base/size, command line, memory descriptions), requiring us to reason about which is which and what to prioritize. It has also resulted in ABI leaks, i.e., internal ABI being promoted to external ABI inadvertently because the bootloader can set the EFI stub's DT properties as well (e.g., "kaslr-seed"). This has become especially problematic with boot environments that want to pretend that EFI boot is being done (to access ACPI and SMBIOS tables, for instance) but have no ability to execute the EFI stub, and so the environment that the EFI stub creates is emulated [poorly, in some cases].
Another downside of treating DT like this is that the DT binary that the kernel receives is different from the one created by the firmware, which is undesirable in the context of secure and measured boot.
Given that LoongArch support in Linux is brand new, we can avoid these pitfalls, and treat the DT strictly as a hardware description, and use a separate handover method between the EFI stub and the kernel. Now that initrd loading and passing the EFI memory map have been refactored into pure EFI routines that use EFI configuration tables, the only thing we need to pass directly is the kernel command line (even if we could pass this via a config table as well, it is used extremely early, so passing it directly is preferred in this case.)
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/loongarch/Kconfig | 3 -- arch/loongarch/include/asm/bootinfo.h | 2 +- arch/loongarch/kernel/efi.c | 30 ++++++++++- arch/loongarch/kernel/env.c | 22 ++++---- arch/loongarch/kernel/head.S | 2 + arch/loongarch/kernel/setup.c | 4 +- drivers/firmware/efi/libstub/Makefile | 13 +++-- drivers/firmware/efi/libstub/loongarch-stub.c | 56 +++++++++++++++++--- 8 files changed, 100 insertions(+), 32 deletions(-)arch/loongarch/Kconfig +0
-3@@ -104,8 +104,6 @@ config LOONGARCH select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK - select OF - select OF_EARLY_FLATTREE select PCI select PCI_DOMAINS_GENERIC select PCI_ECAM if ACPI@@ -311,7 +309,6 @@ config DMI config EFI bool "EFI runtime service support" select UCS2_STRING - select EFI_PARAMS_FROM_FDT select EFI_RUNTIME_WRAPPERS help This enables the kernel to use EFI runtime services that arearch/loongarch/include/asm/bootinfo.h +1
-1@@ -36,7 +36,7 @@ struct loongson_system_configuration { };extern u64 efi_system_table; -extern unsigned long fw_arg0, fw_arg1; +extern unsigned long fw_arg0, fw_arg1, fw_arg2;extern struct loongson_board_info b_info;extern struct loongson_system_configuration loongson_sysconf;arch/loongarch/kernel/efi.c +29
-1@@ -27,8 +27,13 @@static unsigned long efi_nr_tables;static unsigned long efi_config_table; +static unsigned long __initdata boot_memmap =EFI_INVALID_TABLE_ADDR ; +static efi_system_table_t *efi_systab; -static efi_config_table_type_t arch_tables[]__initdata = {{},}; +static efi_config_table_type_t arch_tables[]__initdata = { + {LINUX_EFI_BOOT_MEMMAP_GUID , &boot_memmap,"MEMMAP" }, + {}, +};void __init efi_runtime_init (void ) {@@ -61,6 +66,8 @@ void __init efi_init(void)return ; } +efi_systab_report_header (&efi_systab->hdr, efi_systab->fw_vendor); +set_bit (EFI_64BIT , &efi.flags); efi_nr_tables = efi_systab->nr_tables; efi_config_table = (unsigned long )efi_systab->tables;@@ -72,4 +79,25 @@ void __init efi_init(void)if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI )memblock_reserve (screen_info.lfb_base, screen_info.lfb_size); + +if (boot_memmap !=EFI_INVALID_TABLE_ADDR ) { +struct efi_memory_map_data data; +struct efi_boot_memmap *tbl; + + tbl =early_memremap_ro (boot_memmap,sizeof (*tbl)); +if (tbl) { + data.phys_map = boot_memmap +sizeof (*tbl); + data.size = tbl->map_size; + data.desc_size = tbl->desc_size; + data.desc_version = tbl->desc_ver; + +if (efi_memmap_init_early (&data) <0 ) +panic ("Unable to map EFI memory map.\n" ); + +memblock_reserve (data.phys_map &PAGE_MASK , +PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + +early_memunmap (tbl,sizeof (*tbl)); + } + } }arch/loongarch/kernel/env.c +9
-13@@ -8,7 +8,6 @@#include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> -#include <linux/of_fdt.h> #include <asm/early_ioremap.h> #include <asm/bootinfo.h> #include <asm/loongson.h> @@ -20,21 +19,18 @@ EXPORT_SYMBOL(loongson_sysconf);void __init init_environ (void ) {int efi_boot = fw_arg0; -struct efi_memory_map_data data; -void *fdt_ptr =early_memremap_ro (fw_arg1,SZ_64K ); -if (efi_boot) -set_bit (EFI_BOOT , &efi.flags); -else -clear_bit (EFI_BOOT , &efi.flags); +if (efi_boot) { +char *cmdline =early_memremap_ro (fw_arg2,COMMAND_LINE_SIZE ); -early_init_dt_scan (fdt_ptr); -early_init_fdt_reserve_self (); - efi_system_table =efi_get_fdt_params (&data); +strscpy (boot_command_line, cmdline,COMMAND_LINE_SIZE ); +early_memunmap (cmdline,COMMAND_LINE_SIZE ); -efi_memmap_init_early (&data); -memblock_reserve (data.phys_map &PAGE_MASK , -PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + efi_system_table = fw_arg1; +set_bit (EFI_BOOT , &efi.flags); + }else { +clear_bit (EFI_BOOT , &efi.flags); + } }static int __init init_cpu_fullname (void )arch/loongarch/kernel/head.S +2
-0@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point st.d a0, t0, 0 # firmware arguments la t0, fw_arg1 st.d a1, t0, 0 + la t0, fw_arg2 + st.d a2, t0, 0 /* KSave3 used for percpu base, initialized as 0 */ csrwr zero, PERCPU_BASE_KSarch/loongarch/kernel/setup.c +2
-2@@ -51,7 +51,7 @@ struct screen_info screen_info __section(".data"); -unsigned long fw_arg0, fw_arg1; +unsigned long fw_arg0, fw_arg1, fw_arg2; DEFINE_PER_CPU(unsigned long, kernelsp);struct cpuinfo_loongarch cpu_data[NR_CPUS ]__read_mostly ;@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);void __init platform_init (void ) { -efi_init ();#ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade ();#endif @@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line;init_environ (); +efi_init ();memblock_init ();parse_early_param ();drivers/firmware/efi/libstub/Makefile +8
-5@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie -cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt +cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ -include $(srctree)/include/linux/hidden.h \@@ -60,14 +60,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ alignedmem.o relocate.o vsprintf.o \ systable.o -# include the stub's generic dependencies from lib/ when building for ARM/arm64 -efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c +# include the stub's libfdt dependencies from lib/ when needed +libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \ + fdt_empty_tree.c fdt_sw.c + +lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \ + $(patsubst %.c,lib-%.o,$(libfdt-deps)) $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) -lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o intrinsics.o \ - $(patsubst %.c,lib-%.o,$(efi-deps-y)) +lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.odrivers/firmware/efi/libstub/loongarch-stub.c +49
-8@@ -9,7 +9,8 @@#include <asm/addrspace.h> #include "efistub.h" -typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long fdt); +typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long systab, +unsigned long cmdline);extern int kernel_asize;extern int kernel_fsize;@@ -42,19 +43,60 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,return status; } -void __noreturn efi_enter_kernel (unsigned long entrypoint,unsigned long fdt,unsigned long fdt_size) +struct exit_boot_struct { +efi_memory_desc_t *runtime_map; +int runtime_entry_count; +}; + +static efi_status_t exit_boot_func (struct efi_boot_memmap *map,void *priv) +{ +struct exit_boot_struct *p = priv; + +/* +* Update the memory map with virtual addresses. The function will also +* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME +* entries so that we can pass it straight to SetVirtualAddressMap() +*/ +efi_get_virtmap (map->map, map->map_size, map->desc_size, + p->runtime_map, &p->runtime_entry_count); + +return EFI_SUCCESS ; +} + +efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image, +unsigned long image_addr,char *cmdline_ptr) {kernel_entry_t real_kernel_entry; +struct exit_boot_struct priv; +unsigned long desc_size; +efi_status_t status; +u32 desc_ver; + + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver); +if (status !=EFI_SUCCESS ) { +efi_err ("Unable to retrieve UEFI memory map.\n" ); +return status; + } + +efi_info ("Exiting boot services\n" ); + + efi_novamap = false; + status =efi_exit_boot_services (handle, &priv, exit_boot_func); +if (status !=EFI_SUCCESS ) +return status; + +/* Install the new virtual address map */ +efi_rt_call (set_virtual_address_map, + priv.runtime_entry_count * desc_size, desc_size, + desc_ver, priv.runtime_map);/* Config Direct Mapping */ csr_write64 (CSR_DMW0_INIT ,LOONGARCH_CSR_DMWIN0 );csr_write64 (CSR_DMW1_INIT ,LOONGARCH_CSR_DMWIN1 ); real_kernel_entry = (kernel_entry_t) - ((unsigned long )&kernel_entry - entrypoint +VMLINUX_LOAD_ADDRESS ); + ((unsigned long )&kernel_entry - image_addr +VMLINUX_LOAD_ADDRESS ); -if (!efi_novamap) -real_kernel_entry (true, fdt); -else -real_kernel_entry (false, fdt); +real_kernel_entry (true, (unsigned long )efi_system_table, + (unsigned long )cmdline_ptr); } --2.35.1
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 7 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpi
Quoted 8 lines
The current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;
DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
Quoted 1 line
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
What we might do is
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
Quoted 337 lines · Ard Biesheuvel
Quoted 335 lines
LoongArch does not use FDT or DT natively [yet], and the only reason it currently uses it is so that it can reuse the existing EFI stub code.
Overloading the DT with data passed between the EFI stub and the core kernel has been a source of problems: there is the overlap between information provided by EFI which DT can also provide (initrd base/size, command line, memory descriptions), requiring us to reason about which is which and what to prioritize. It has also resulted in ABI leaks, i.e., internal ABI being promoted to external ABI inadvertently because the bootloader can set the EFI stub's DT properties as well (e.g., "kaslr-seed"). This has become especially problematic with boot environments that want to pretend that EFI boot is being done (to access ACPI and SMBIOS tables, for instance) but have no ability to execute the EFI stub, and so the environment that the EFI stub creates is emulated [poorly, in some cases].
Another downside of treating DT like this is that the DT binary that the kernel receives is different from the one created by the firmware, which is undesirable in the context of secure and measured boot.
Given that LoongArch support in Linux is brand new, we can avoid these pitfalls, and treat the DT strictly as a hardware description, and use a separate handover method between the EFI stub and the kernel. Now that initrd loading and passing the EFI memory map have been refactored into pure EFI routines that use EFI configuration tables, the only thing we need to pass directly is the kernel command line (even if we could pass this via a config table as well, it is used extremely early, so passing it directly is preferred in this case.)
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/loongarch/Kconfig | 3 -- arch/loongarch/include/asm/bootinfo.h | 2 +- arch/loongarch/kernel/efi.c | 30 ++++++++++- arch/loongarch/kernel/env.c | 22 ++++---- arch/loongarch/kernel/head.S | 2 + arch/loongarch/kernel/setup.c | 4 +- drivers/firmware/efi/libstub/Makefile | 13 +++-- drivers/firmware/efi/libstub/loongarch-stub.c | 56 +++++++++++++++++--- 8 files changed, 100 insertions(+), 32 deletions(-)arch/loongarch/Kconfig +0
-3@@ -104,8 +104,6 @@ config LOONGARCH select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK - select OF - select OF_EARLY_FLATTREE select PCI select PCI_DOMAINS_GENERIC select PCI_ECAM if ACPI@@ -311,7 +309,6 @@ config DMI config EFI bool "EFI runtime service support" select UCS2_STRING - select EFI_PARAMS_FROM_FDT select EFI_RUNTIME_WRAPPERS help This enables the kernel to use EFI runtime services that arearch/loongarch/include/asm/bootinfo.h +1
-1@@ -36,7 +36,7 @@ struct loongson_system_configuration { };extern u64 efi_system_table; -extern unsigned long fw_arg0, fw_arg1; +extern unsigned long fw_arg0, fw_arg1, fw_arg2;extern struct loongson_board_info b_info;extern struct loongson_system_configuration loongson_sysconf;arch/loongarch/kernel/efi.c +29
-1@@ -27,8 +27,13 @@static unsigned long efi_nr_tables;static unsigned long efi_config_table; +static unsigned long __initdata boot_memmap =EFI_INVALID_TABLE_ADDR ; +static efi_system_table_t *efi_systab; -static efi_config_table_type_t arch_tables[]__initdata = {{},}; +static efi_config_table_type_t arch_tables[]__initdata = { + {LINUX_EFI_BOOT_MEMMAP_GUID , &boot_memmap,"MEMMAP" }, + {}, +};void __init efi_runtime_init (void ) {@@ -61,6 +66,8 @@ void __init efi_init(void)return ; } +efi_systab_report_header (&efi_systab->hdr, efi_systab->fw_vendor); +set_bit (EFI_64BIT , &efi.flags); efi_nr_tables = efi_systab->nr_tables; efi_config_table = (unsigned long )efi_systab->tables;@@ -72,4 +79,25 @@ void __init efi_init(void)if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI )memblock_reserve (screen_info.lfb_base, screen_info.lfb_size); + +if (boot_memmap !=EFI_INVALID_TABLE_ADDR ) { +struct efi_memory_map_data data; +struct efi_boot_memmap *tbl; + + tbl =early_memremap_ro (boot_memmap,sizeof (*tbl)); +if (tbl) { + data.phys_map = boot_memmap +sizeof (*tbl); + data.size = tbl->map_size; + data.desc_size = tbl->desc_size; + data.desc_version = tbl->desc_ver; + +if (efi_memmap_init_early (&data) <0 ) +panic ("Unable to map EFI memory map.\n" ); + +memblock_reserve (data.phys_map &PAGE_MASK , +PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + +early_memunmap (tbl,sizeof (*tbl)); + } + } }arch/loongarch/kernel/env.c +9
-13@@ -8,7 +8,6 @@#include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> -#include <linux/of_fdt.h> #include <asm/early_ioremap.h> #include <asm/bootinfo.h> #include <asm/loongson.h> @@ -20,21 +19,18 @@ EXPORT_SYMBOL(loongson_sysconf);void __init init_environ (void ) {int efi_boot = fw_arg0; -struct efi_memory_map_data data; -void *fdt_ptr =early_memremap_ro (fw_arg1,SZ_64K ); -if (efi_boot) -set_bit (EFI_BOOT , &efi.flags); -else -clear_bit (EFI_BOOT , &efi.flags); +if (efi_boot) { +char *cmdline =early_memremap_ro (fw_arg2,COMMAND_LINE_SIZE ); -early_init_dt_scan (fdt_ptr); -early_init_fdt_reserve_self (); - efi_system_table =efi_get_fdt_params (&data); +strscpy (boot_command_line, cmdline,COMMAND_LINE_SIZE ); +early_memunmap (cmdline,COMMAND_LINE_SIZE ); -efi_memmap_init_early (&data); -memblock_reserve (data.phys_map &PAGE_MASK , -PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + efi_system_table = fw_arg1; +set_bit (EFI_BOOT , &efi.flags); + }else { +clear_bit (EFI_BOOT , &efi.flags); + } }static int __init init_cpu_fullname (void )arch/loongarch/kernel/head.S +2
-0@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point st.d a0, t0, 0 # firmware arguments la t0, fw_arg1 st.d a1, t0, 0 + la t0, fw_arg2 + st.d a2, t0, 0 /* KSave3 used for percpu base, initialized as 0 */ csrwr zero, PERCPU_BASE_KSarch/loongarch/kernel/setup.c +2
-2@@ -51,7 +51,7 @@ struct screen_info screen_info __section(".data"); -unsigned long fw_arg0, fw_arg1; +unsigned long fw_arg0, fw_arg1, fw_arg2; DEFINE_PER_CPU(unsigned long, kernelsp);struct cpuinfo_loongarch cpu_data[NR_CPUS ]__read_mostly ;@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);void __init platform_init (void ) { -efi_init ();#ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade ();#endif @@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line;init_environ (); +efi_init ();memblock_init ();parse_early_param ();drivers/firmware/efi/libstub/Makefile +8
-5@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie -cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt +cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ -include $(srctree)/include/linux/hidden.h \@@ -60,14 +60,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ alignedmem.o relocate.o vsprintf.o \ systable.o -# include the stub's generic dependencies from lib/ when building for ARM/arm64 -efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c +# include the stub's libfdt dependencies from lib/ when needed +libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \ + fdt_empty_tree.c fdt_sw.c + +lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \ + $(patsubst %.c,lib-%.o,$(libfdt-deps)) $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) -lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o intrinsics.o \ - $(patsubst %.c,lib-%.o,$(efi-deps-y)) +lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.odrivers/firmware/efi/libstub/loongarch-stub.c +49
-8@@ -9,7 +9,8 @@#include <asm/addrspace.h> #include "efistub.h" -typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long fdt); +typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long systab, +unsigned long cmdline);extern int kernel_asize;extern int kernel_fsize;@@ -42,19 +43,60 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,return status; } -void __noreturn efi_enter_kernel (unsigned long entrypoint,unsigned long fdt,unsigned long fdt_size) +struct exit_boot_struct { +efi_memory_desc_t *runtime_map; +int runtime_entry_count; +}; + +static efi_status_t exit_boot_func (struct efi_boot_memmap *map,void *priv) +{ +struct exit_boot_struct *p = priv; + +/* +* Update the memory map with virtual addresses. The function will also +* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME +* entries so that we can pass it straight to SetVirtualAddressMap() +*/ +efi_get_virtmap (map->map, map->map_size, map->desc_size, + p->runtime_map, &p->runtime_entry_count); + +return EFI_SUCCESS ; +} + +efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image, +unsigned long image_addr,char *cmdline_ptr) {kernel_entry_t real_kernel_entry; +struct exit_boot_struct priv; +unsigned long desc_size; +efi_status_t status; +u32 desc_ver; + + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver); +if (status !=EFI_SUCCESS ) { +efi_err ("Unable to retrieve UEFI memory map.\n" ); +return status; + } + +efi_info ("Exiting boot services\n" ); + + efi_novamap = false; + status =efi_exit_boot_services (handle, &priv, exit_boot_func); +if (status !=EFI_SUCCESS ) +return status; + +/* Install the new virtual address map */ +efi_rt_call (set_virtual_address_map, + priv.runtime_entry_count * desc_size, desc_size, + desc_ver, priv.runtime_map);/* Config Direct Mapping */ csr_write64 (CSR_DMW0_INIT ,LOONGARCH_CSR_DMWIN0 );csr_write64 (CSR_DMW1_INIT ,LOONGARCH_CSR_DMWIN1 ); real_kernel_entry = (kernel_entry_t) - ((unsigned long )&kernel_entry - entrypoint +VMLINUX_LOAD_ADDRESS ); + ((unsigned long )&kernel_entry - image_addr +VMLINUX_LOAD_ADDRESS ); -if (!efi_novamap) -real_kernel_entry (true, fdt); -else -real_kernel_entry (false, fdt); +real_kernel_entry (true, (unsigned long )efi_system_table, + (unsigned long )cmdline_ptr); } --2.35.1
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdline
Quoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
Quoted 13 lines
Quoted 2 lines
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
Quoted 6 lines
What we might do is
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
I think the efi boot flag is still needed, even boot from efistub. Because if boot with "efi=novamap", the efi runtime should be disabled. Then we need efi_enabled(EFI_BOOT) to be false in efi_init().
Huacai
Quoted 339 lines
Quoted 339 lines · Ard Biesheuvel
Quoted 335 lines
LoongArch does not use FDT or DT natively [yet], and the only reason it currently uses it is so that it can reuse the existing EFI stub code.
Overloading the DT with data passed between the EFI stub and the core kernel has been a source of problems: there is the overlap between information provided by EFI which DT can also provide (initrd base/size, command line, memory descriptions), requiring us to reason about which is which and what to prioritize. It has also resulted in ABI leaks, i.e., internal ABI being promoted to external ABI inadvertently because the bootloader can set the EFI stub's DT properties as well (e.g., "kaslr-seed"). This has become especially problematic with boot environments that want to pretend that EFI boot is being done (to access ACPI and SMBIOS tables, for instance) but have no ability to execute the EFI stub, and so the environment that the EFI stub creates is emulated [poorly, in some cases].
Another downside of treating DT like this is that the DT binary that the kernel receives is different from the one created by the firmware, which is undesirable in the context of secure and measured boot.
Given that LoongArch support in Linux is brand new, we can avoid these pitfalls, and treat the DT strictly as a hardware description, and use a separate handover method between the EFI stub and the kernel. Now that initrd loading and passing the EFI memory map have been refactored into pure EFI routines that use EFI configuration tables, the only thing we need to pass directly is the kernel command line (even if we could pass this via a config table as well, it is used extremely early, so passing it directly is preferred in this case.)
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/loongarch/Kconfig | 3 -- arch/loongarch/include/asm/bootinfo.h | 2 +- arch/loongarch/kernel/efi.c | 30 ++++++++++- arch/loongarch/kernel/env.c | 22 ++++---- arch/loongarch/kernel/head.S | 2 + arch/loongarch/kernel/setup.c | 4 +- drivers/firmware/efi/libstub/Makefile | 13 +++-- drivers/firmware/efi/libstub/loongarch-stub.c | 56 +++++++++++++++++--- 8 files changed, 100 insertions(+), 32 deletions(-)arch/loongarch/Kconfig +0
-3@@ -104,8 +104,6 @@ config LOONGARCH select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK - select OF - select OF_EARLY_FLATTREE select PCI select PCI_DOMAINS_GENERIC select PCI_ECAM if ACPI@@ -311,7 +309,6 @@ config DMI config EFI bool "EFI runtime service support" select UCS2_STRING - select EFI_PARAMS_FROM_FDT select EFI_RUNTIME_WRAPPERS help This enables the kernel to use EFI runtime services that arearch/loongarch/include/asm/bootinfo.h +1
-1@@ -36,7 +36,7 @@ struct loongson_system_configuration { };extern u64 efi_system_table; -extern unsigned long fw_arg0, fw_arg1; +extern unsigned long fw_arg0, fw_arg1, fw_arg2;extern struct loongson_board_info b_info;extern struct loongson_system_configuration loongson_sysconf;arch/loongarch/kernel/efi.c +29
-1@@ -27,8 +27,13 @@static unsigned long efi_nr_tables;static unsigned long efi_config_table; +static unsigned long __initdata boot_memmap =EFI_INVALID_TABLE_ADDR ; +static efi_system_table_t *efi_systab; -static efi_config_table_type_t arch_tables[]__initdata = {{},}; +static efi_config_table_type_t arch_tables[]__initdata = { + {LINUX_EFI_BOOT_MEMMAP_GUID , &boot_memmap,"MEMMAP" }, + {}, +};void __init efi_runtime_init (void ) {@@ -61,6 +66,8 @@ void __init efi_init(void)return ; } +efi_systab_report_header (&efi_systab->hdr, efi_systab->fw_vendor); +set_bit (EFI_64BIT , &efi.flags); efi_nr_tables = efi_systab->nr_tables; efi_config_table = (unsigned long )efi_systab->tables;@@ -72,4 +79,25 @@ void __init efi_init(void)if (screen_info.orig_video_isVGA ==VIDEO_TYPE_EFI )memblock_reserve (screen_info.lfb_base, screen_info.lfb_size); + +if (boot_memmap !=EFI_INVALID_TABLE_ADDR ) { +struct efi_memory_map_data data; +struct efi_boot_memmap *tbl; + + tbl =early_memremap_ro (boot_memmap,sizeof (*tbl)); +if (tbl) { + data.phys_map = boot_memmap +sizeof (*tbl); + data.size = tbl->map_size; + data.desc_size = tbl->desc_size; + data.desc_version = tbl->desc_ver; + +if (efi_memmap_init_early (&data) <0 ) +panic ("Unable to map EFI memory map.\n" ); + +memblock_reserve (data.phys_map &PAGE_MASK , +PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + +early_memunmap (tbl,sizeof (*tbl)); + } + } }arch/loongarch/kernel/env.c +9
-13@@ -8,7 +8,6 @@#include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> -#include <linux/of_fdt.h> #include <asm/early_ioremap.h> #include <asm/bootinfo.h> #include <asm/loongson.h> @@ -20,21 +19,18 @@ EXPORT_SYMBOL(loongson_sysconf);void __init init_environ (void ) {int efi_boot = fw_arg0; -struct efi_memory_map_data data; -void *fdt_ptr =early_memremap_ro (fw_arg1,SZ_64K ); -if (efi_boot) -set_bit (EFI_BOOT , &efi.flags); -else -clear_bit (EFI_BOOT , &efi.flags); +if (efi_boot) { +char *cmdline =early_memremap_ro (fw_arg2,COMMAND_LINE_SIZE ); -early_init_dt_scan (fdt_ptr); -early_init_fdt_reserve_self (); - efi_system_table =efi_get_fdt_params (&data); +strscpy (boot_command_line, cmdline,COMMAND_LINE_SIZE ); +early_memunmap (cmdline,COMMAND_LINE_SIZE ); -efi_memmap_init_early (&data); -memblock_reserve (data.phys_map &PAGE_MASK , -PAGE_ALIGN (data.size + (data.phys_map & ~PAGE_MASK ))); + efi_system_table = fw_arg1; +set_bit (EFI_BOOT , &efi.flags); + }else { +clear_bit (EFI_BOOT , &efi.flags); + } }static int __init init_cpu_fullname (void )arch/loongarch/kernel/head.S +2
-0@@ -67,6 +67,8 @@ SYM_CODE_START(kernel_entry) # kernel entry point st.d a0, t0, 0 # firmware arguments la t0, fw_arg1 st.d a1, t0, 0 + la t0, fw_arg2 + st.d a2, t0, 0 /* KSave3 used for percpu base, initialized as 0 */ csrwr zero, PERCPU_BASE_KSarch/loongarch/kernel/setup.c +2
-2@@ -51,7 +51,7 @@ struct screen_info screen_info __section(".data"); -unsigned long fw_arg0, fw_arg1; +unsigned long fw_arg0, fw_arg1, fw_arg2; DEFINE_PER_CPU(unsigned long, kernelsp);struct cpuinfo_loongarch cpu_data[NR_CPUS ]__read_mostly ;@@ -187,7 +187,6 @@ early_param("mem", early_parse_mem);void __init platform_init (void ) { -efi_init ();#ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade ();#endif @@ -347,6 +346,7 @@ void __init setup_arch(char **cmdline_p) *cmdline_p = boot_command_line;init_environ (); +efi_init ();memblock_init ();parse_early_param ();drivers/firmware/efi/libstub/Makefile +8
-5@@ -29,7 +29,7 @@ cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ -fpie -cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt +cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ -include $(srctree)/include/linux/hidden.h \@@ -60,14 +60,17 @@ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ alignedmem.o relocate.o vsprintf.o \ systable.o -# include the stub's generic dependencies from lib/ when building for ARM/arm64 -efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c +# include the stub's libfdt dependencies from lib/ when needed +libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \ + fdt_empty_tree.c fdt_sw.c + +lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \ + $(patsubst %.c,lib-%.o,$(libfdt-deps)) $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) -lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o fdt.o string.o intrinsics.o \ - $(patsubst %.c,lib-%.o,$(efi-deps-y)) +lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64-stub.odrivers/firmware/efi/libstub/loongarch-stub.c +49
-8@@ -9,7 +9,8 @@#include <asm/addrspace.h> #include "efistub.h" -typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long fdt); +typedef void __noreturn (*kernel_entry_t )(bool efi,unsigned long systab, +unsigned long cmdline);extern int kernel_asize;extern int kernel_fsize;@@ -42,19 +43,60 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,return status; } -void __noreturn efi_enter_kernel (unsigned long entrypoint,unsigned long fdt,unsigned long fdt_size) +struct exit_boot_struct { +efi_memory_desc_t *runtime_map; +int runtime_entry_count; +}; + +static efi_status_t exit_boot_func (struct efi_boot_memmap *map,void *priv) +{ +struct exit_boot_struct *p = priv; + +/* +* Update the memory map with virtual addresses. The function will also +* populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME +* entries so that we can pass it straight to SetVirtualAddressMap() +*/ +efi_get_virtmap (map->map, map->map_size, map->desc_size, + p->runtime_map, &p->runtime_entry_count); + +return EFI_SUCCESS ; +} + +efi_status_t efi_boot_kernel (void *handle,efi_loaded_image_t *image, +unsigned long image_addr,char *cmdline_ptr) {kernel_entry_t real_kernel_entry; +struct exit_boot_struct priv; +unsigned long desc_size; +efi_status_t status; +u32 desc_ver; + + status =efi_alloc_virtmap (&priv.runtime_map, &desc_size, &desc_ver); +if (status !=EFI_SUCCESS ) { +efi_err ("Unable to retrieve UEFI memory map.\n" ); +return status; + } + +efi_info ("Exiting boot services\n" ); + + efi_novamap = false; + status =efi_exit_boot_services (handle, &priv, exit_boot_func); +if (status !=EFI_SUCCESS ) +return status; + +/* Install the new virtual address map */ +efi_rt_call (set_virtual_address_map, + priv.runtime_entry_count * desc_size, desc_size, + desc_ver, priv.runtime_map);/* Config Direct Mapping */ csr_write64 (CSR_DMW0_INIT ,LOONGARCH_CSR_DMWIN0 );csr_write64 (CSR_DMW1_INIT ,LOONGARCH_CSR_DMWIN1 ); real_kernel_entry = (kernel_entry_t) - ((unsigned long )&kernel_entry - entrypoint +VMLINUX_LOAD_ADDRESS ); + ((unsigned long )&kernel_entry - image_addr +VMLINUX_LOAD_ADDRESS ); -if (!efi_novamap) -real_kernel_entry (true, fdt); -else -real_kernel_entry (false, fdt); +real_kernel_entry (true, (unsigned long )efi_system_table, + (unsigned long )cmdline_ptr); } --2.35.1
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);
Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Do you intend to support non-EFI DT boot by the way?
So
a2 != 0x0 means old world
a0 != 0x0 means EFI boot, a1 is the command line
a0 == 0x0 means !EFI boot, a1 is the DT
Quoted 15 lines
Quoted 15 lines
Quoted 2 lines
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
What we might do is
Quoted 9 lines
Quoted 4 lines
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
I think the efi boot flag is still needed, even boot from efistub. Because if boot with "efi=novamap", the efi runtime should be disabled. Then we need
efi_enabled(EFI_BOOT)to be false inefi_init().
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code, efi_novamap is set to false unconditionally.
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 8 lines
Do you intend to support non-EFI DT boot by the way?
So
a2 !=
0x0means old world
a0 !=0x0means EFI boot, a1 is the command line
a0 ==0x0means !EFI boot, a1 is the DT
Note: the above applies if we decide to merge the EFI boolean and the system table pointer into register #0.
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
In reply to Ard BiesheuvelHi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world). But I have another question: is it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?
Quoted 32 lines
So
a2 !=
0x0means old world
a0 !=0x0means EFI boot, a1 is the command line
a0 ==0x0means !EFI boot, a1 is the DTQuoted 15 lines
Quoted 15 lines
Quoted 2 lines
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
What we might do is
Quoted 9 lines
Quoted 4 lines
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
I think the efi boot flag is still needed, even boot from efistub. Because if boot with "efi=novamap", the efi runtime should be disabled. Then we need
efi_enabled(EFI_BOOT)to be false inefi_init().
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.
Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack efi_novamap. So please keep the efi boot flag, thanks.
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?
If you rely on DT only for the hardware description, then loading it from efi_init() should be fine.
Quoted 32 lines
Quoted 32 lines
So
a2 !=
0x0means old world
a0 !=0x0means EFI boot, a1 is the command line
a0 ==0x0means !EFI boot, a1 is the DTQuoted 24 lines
Quoted 13 lines
Quoted 2 lines
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
Quoted 6 lines
What we might do is
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
I think the efi boot flag is still needed, even boot from efistub. Because if boot with "efi=novamap", the efi runtime should be disabled. Then we need
efi_enabled(EFI_BOOT)to be false inefi_init().
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.
Fair enough. Do you have any uses for efi_novamap in mind?
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 57 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 7 lines
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.
OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
Quoted 36 lines
Quoted 36 lines
Quoted 36 lines
So
a2 !=
0x0means old world
a0 !=0x0means EFI boot, a1 is the command line
a0 ==0x0means !EFI boot, a1 is the DTQuoted 15 lines
Quoted 15 lines
Quoted 2 lines
2, arm64, riscv and loongarch can use similar logics (light FDT);
No need to repeat a mistake. I intend to fix RISC-V next.
Quoted 3 lines
3, out-of-tree patches can make compatibility with the old world easier by just judging whether a2 is zero.
The whole point of this series is that the EFI stub should not be touching the DT at all. In other words, there is no DT pointer, so the current method needs to be revised.
What we might do is
Quoted 9 lines
Quoted 4 lines
a0=systemtable, a1=cmdline
as any non-zero value is treated as logic true. That way, your logic to test a2 is zero will still work.
I think the efi boot flag is still needed, even boot from efistub. Because if boot with "efi=novamap", the efi runtime should be disabled. Then we need
efi_enabled(EFI_BOOT)to be false inefi_init().I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.
Quoted 6 lines
Quoted 4 lines
Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?
I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?
Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.
Quoted 4 lines
Quoted 1 line
Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
It works fine now.
However, clearing the EFI_BOOT flag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Quoted 4 lines
Quoted 1 line
Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?
OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead. But I think support "efi=novamap" is not a bad idea (maybe I misunderstood its usage).
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).
It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls SetVirtualAddressMap() *after* creating the new mappings, and some broken firmware drivers will access those regions too early.
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the efi_novamap logic for now - we can always revisit it later.
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.
Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" in efi_init, i.e., if (boot_memmap == EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of the if() condition in init_environ() looks better. 4, I prefer "kernel_addr" rather than "image_addr" in efi_boot_kernel(). 5, It seems that one line is enough for the last statement in efi_boot_kernel().
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Huacai
Quoted 1 line
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.
Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().
OK
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 133 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed. The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().
Quoted 7 lines
OK
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-next
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 13 lines · Huacai Chen
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineQuoted 7 lines
Quoted 2 lines
I prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and non-EFI boot. We *really* should keep these separate, given the experience on ARM, where other projects invent ways to pass those values to the kernel without going through the stub.
In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-next
Thanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5 -0
@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }
So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Hi, Ard,
Quoted 173 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 33 lines · Huacai Chen
Hi, Ard,
Quoted 22 lines · Ard Biesheuvel
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.In the last patch I see:
(quoted diff) +5
-0+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K); + + early_init_dt_scan(fdt_ptr); + early_init_fdt_reserve_self(); + clear_bit(EFI_BOOT, &efi.flags);Quoted 4 lines
So I suppose for the DT system that means a0=efi boot flag, a1=fdt pointer, a2=cmdline? Then it is not exactly the same as the ACPI system, but similar.
No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Quoted 6 lines
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 180 lines · Huacai Chen
Hi, Ard,
Quoted 176 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
Quoted 37 lines · Huacai Chen
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so a0=0x0 (non-efi), a1=DT, a2=0x0
Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given that we cannot make use of the runtime services that way. So in my code,
efi_novamapis set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
Quoted 11 lines
Quoted 3 lines
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?
There are two options:
- use initrdmem= on the command line
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 194 lines · Ard Biesheuvel
Quoted 180 lines · Huacai Chen
Hi, Ard,
Quoted 176 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 47 lines · Huacai Chen
Hi, Ard,
Quoted 43 lines · Ard Biesheuvel
On Mon, 19 Sept 2022 at 08:06, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so
a0=0x0 (non-efi), a1=DT, a2=0x0Quoted 4 lines
Quoted 1 line
Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag, a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2, which looks similar to the old-world).
Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given
that we cannot make use of the runtime services that way. So in my
code, efi_novamap is set to false unconditionally.Emm, I prefer to support "efi=novamap", the core kernel has already supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
Quoted 11 lines
Quoted 3 lines
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?
Quoted 2 lines
There are two options:
- use initrdmem= on the command line
This is not a good way, even if the second kernel handle "initrdmem=", it will conflict with the config table.
Quoted 2 lines
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
This way seems practicable, but we don't know how to handle it in kexec-tools. :(
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 196 lines · Huacai Chen
Quoted 194 lines · Ard Biesheuvel
Quoted 191 lines · Huacai Chen
Hi, Ard,
Quoted 173 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
Quoted 51 lines · Huacai Chen
Hi, Ard,
On Mon, Sep 19, 2022 at 2:22 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 08:06, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so
a0=0x0 (non-efi), a1=DT, a2=0x0Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag,
a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2,
which looks similar to the old-world).Excellent. If non-EFI boot is not supported, we can drop the code that deals with that.
Quoted 4 lines
But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current
way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it from
efi_init()should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
Quoted 7 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given
that we cannot make use of the runtime services that way. So in my
code, efi_novamap is set to false unconditionally.
Emm, I prefer to support "efi=novamap", the core kernel has already
supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for
efi_novamapin mind?I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Quoted 6 lines
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?
Quoted 5 lines
Quoted 2 lines
There are two options:
- use initrdmem= on the command lineThis is not a good way, even if the second kernel handle "initrdmem=", it will conflict with the config table.
It will not conflict - initrdmem= supersedes the INITRD table because early param passing happens after efi_init().
Quoted 5 lines
Quoted 2 lines
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
This way seems practicable, but we don't know how to handle it in kexec-tools. :(
Good point. Let me think a bit about this.
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 207 lines · Ard Biesheuvel
Quoted 196 lines · Huacai Chen
Quoted 194 lines · Ard Biesheuvel
Quoted 191 lines · Huacai Chen
Hi, Ard,
Quoted 173 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 64 lines · Huacai Chen
Quoted 62 lines · Ard Biesheuvel
On Mon, 19 Sept 2022 at 12:33, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 2:22 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 08:06, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so
a0=0x0 (non-efi), a1=DT, a2=0x0Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag,
a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2,
which looks similar to the old-world).Excellent. If non-EFI boot is not supported, we can drop the code that
deals with that.But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current
way DT is the earliest thing)?Quoted 5 lines
Quoted 2 lines
If you rely on DT only for the hardware description, then loading it
from efi_init() should be fine.OK, then please drop patch #12 at this time. It can be added when we add Loongson-2K support.
OK
Quoted 12 lines
Quoted 9 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given
that we cannot make use of the runtime services that way. So in my
code, efi_novamap is set to false unconditionally.
Emm, I prefer to support "efi=novamap", the core kernel has already
supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for efi_novamap in mind?
I usually use "efi=novamap" in EFI shell to see whether it can work well without runtime. And I think I will modify this patch these days because in another thread you said that this series cannot boot.
Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Quoted 6 lines
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?Quoted 5 lines
Quoted 2 lines
There are two options:
- use initrdmem= on the command lineThis is not a good way, even if the second kernel handle "initrdmem=", it will conflict with the config table.
It will not conflict - initrdmem= supersedes the INITRD table because early param passing happens after
efi_init().
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
This way seems practicable, but we don't know how to handle it in kexec-tools. :(
Good point. Let me think a bit about this.
OK, then let's go back to this series itself. :)
I have seen the latest code in your git repo, I don't think we need efi_disable_rt. Instead, setting/clearing EFI_BOOT according to a0 as before seems reasonable.
If efi_novamap breaks something, I can accept "set efi_novamap to false" in the previous version, or just ignore its value in the efistub, but a0 should clearly be the indicator of EFI_BOOT.
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 215 lines · Huacai Chen
Quoted 213 lines · Ard Biesheuvel
Quoted 196 lines · Huacai Chen
Quoted 194 lines · Ard Biesheuvel
Quoted 191 lines · Huacai Chen
Hi, Ard,
Quoted 173 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
Quoted 69 lines · Huacai Chen
On Mon, Sep 19, 2022 at 6:37 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 12:33, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 2:22 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 08:06, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so
a0=0x0 (non-efi), a1=DT, a2=0x0Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag,
a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2,
which looks similar to the old-world).Excellent. If non-EFI boot is not supported, we can drop the code that
deals with that.But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current
way DT is the earliest thing)?If you rely on DT only for the hardware description, then loading it
from efi_init() should be fine.
OK, then please drop patch #12 at this time. It can be added when we
add Loongson-2K support.OK
Quoted 12 lines
I don't think it makes sense to allow efi=novamap on LoongArch, given
that we cannot make use of the runtime services that way. So in my
code, efi_novamap is set to false unconditionally.
Emm, I prefer to support "efi=novamap", the core kernel has already
supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for efi_novamap in mind?
I usually use "efi=novamap" in EFI shell to see whether it can work
well without runtime. And I think I will modify this patch these days
because in another thread you said that this series cannot boot.Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the
EFI_BOOTflag is not the correct way to disable runtime services only. And note that we also have efi=noruntime - does that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Quoted 6 lines
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?Quoted 5 lines
Quoted 2 lines
There are two options:
- use initrdmem= on the command lineThis is not a good way, even if the second kernel handle "initrdmem=", it will conflict with the config table.
It will not conflict - initrdmem= supersedes the INITRD table because early param passing happens after
efi_init().Quoted 5 lines
Quoted 2 lines
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
This way seems practicable, but we don't know how to handle it in kexec-tools. :(
Quoted 7 lines
Quoted 1 line
Good point. Let me think a bit about this.
OK, then let's go back to this series itself. :)
I have seen the latest code in your git repo, I don't think we need
efi_disable_rt. Instead, setting/clearingEFI_BOOTaccording to a0 as before seems reasonable.
No, not really. EFI_BOOT basically means 'did I boot via EFI?' and strictly, you should not be attempting to access the EFI system table or parse EFI config tables unless EFI_BOOT is true.
Deviating from this makes it more difficult for generic code to reason about what parts of EFI are active on a given system.
Quoted 4 lines
If
efi_novamapbreaks something, I can accept "setefi_novamapto false" in the previous version, or just ignore its value in the efistub, but a0 should clearly be the indicator ofEFI_BOOT.
I'm fine with keeping efi_novamap if you think it has a value. To me, it seems rather pointless, because it prevents you from using the runtime services.
If you want a0 to control the EFI boot flag, you should find another way to control whether runtime services can be used, because they are really two different things.
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Hi, Ard,
Quoted 237 lines · Ard Biesheuvel
Quoted 215 lines · Huacai Chen
Quoted 213 lines · Ard Biesheuvel
Quoted 196 lines · Huacai Chen
Quoted 194 lines · Ard Biesheuvel
Quoted 191 lines · Huacai Chen
Hi, Ard,
Quoted 173 lines · Ard Biesheuvel
Quoted 137 lines · Huacai Chen
Quoted 135 lines · Ard Biesheuvel
Quoted 118 lines · Huacai Chen
Quoted 110 lines · Ard Biesheuvel
Quoted 89 lines · Huacai Chen
Quoted 87 lines · Ard Biesheuvel
On Mon, 19 Sept 2022 at 12:47, Huacai Chen <[email protected]> wrote:
On Mon, Sep 19, 2022 at 6:37 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 12:33, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 2:22 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 08:06, Huacai Chen <[email protected]> wrote:
Hi, Ard,
On Mon, Sep 19, 2022 at 1:15 PM Ard Biesheuvel <[email protected]> wrote:
On Mon, 19 Sept 2022 at 03:58, Huacai Chen <[email protected]> wrote:
Hi, Ard,
I think the parameters passed to the core kernel need to be discussed.
The old way (so-called old world):
a0=argc, a1=argv, a1=bpiThe current way (so-called new world):
a0=efi boot flag, a1=fdt pointerThe new way (in this patchset):
a0=efi boot flag, a1=systemtable, a2=cmdlineI prefer to use the current way, there are 3 reasons:
1, both acpi system and dt system can use the same parameters passing method;DT systems will use this too. The distinction is between EFI boot and
non-EFI boot. We *really* should keep these separate, given the
experience on ARM, where other projects invent ways to pass those
values to the kernel without going through the stub.
In the last patch I see:
+ void *fdt_ptr = early_memremap_ro(fw_arg1, SZ_64K);
+
+ early_init_dt_scan(fdt_ptr);
+ early_init_fdt_reserve_self();
+
clear_bit(EFI_BOOT, &efi.flags);
So I suppose for the DT system that means a0=efi boot flag, a1=fdt
pointer, a2=cmdline? Then it is not exactly the same as the ACPI
system, but similar.No, for non-EFI DT boot, the command line is passed via the DT, so
a0=0x0 (non-efi), a1=DT, a2=0x0Do you intend to support non-EFI DT boot by the way?
I think we needn't support non-EFI DT boot, so a0=efi boot flag,
a1=systemtable, a2=cmdline is just OK (or maybe we can exchange a1/a2,
which looks similar to the old-world).Excellent. If non-EFI boot is not supported, we can drop the code that
deals with that.But I have another question: is
it early enough to get DT from systemtable for DT boot (in the current
way DT is the earliest thing)?If you rely on DT only for the hardware description, then loading it
from efi_init() should be fine.
OK, then please drop patch #12 at this time. It can be added when we
add Loongson-2K support.OK
I don't think it makes sense to allow efi=novamap on LoongArch, given
that we cannot make use of the runtime services that way. So in my
code, efi_novamap is set to false unconditionally.
Emm, I prefer to support "efi=novamap", the core kernel has already
supported "noefi" to disable runtime, I don't want to hack
efi_novamap. So please keep the efi boot flag, thanks.Fair enough. Do you have any uses for efi_novamap in mind?
I usually use "efi=novamap" in EFI shell to see whether it can work
well without runtime. And I think I will modify this patch these days
because in another thread you said that this series cannot boot.Quoted 7 lines
Quoted 5 lines
It works fine now.
However, clearing the EFI_BOOT flag is not the correct way to disable
runtime services only. And note that we also have efi=noruntime - does
that currently work on LoongArch?OK, but we don't need to add a new "efi=noruntime" parameter, I can use "noefi" instead.
OK
Quoted 3 lines
But I think support "efi=novamap" is not a bad
idea (maybe I misunderstood its usage).It basically exists to deal with broken EFI firmware on ARM laptops that were only intended to run Windows. Windows calls
SetVirtualAddressMap()*after* creating the new mappings, and some broken firmware drivers will access those regions too early.Quoted 6 lines
On Linux, we install the mapping first, and then much later, we actually create the mappings and only activate them on a single CPU while the EFI runtime service call is in progress.
In any case, I will reinstate the
efi_novamaplogic for now - we can always revisit it later.Quoted 12 lines
OK, now I think there are no big problems. Only some bikesheddings:
1, Please use "a0=efi boot flag, a1=cmdline a2=systemtable" to pass boot information, it looks most similar to the old-world, and we can distinguish old-world/new-world by judging whether a0 is greater than 1.
2, I prefer "early return" inefi_init, i.e., if (boot_memmap==EFI_INVALID_TABLE_ADDR) then return immediately, this makes indentation look better.
3, Declare "cmdline" out of theif()condition ininit_environ()looks better. 4, I prefer "kernel_addr" rather than "image_addr" inefi_boot_kernel(). 5, It seems that one line is enough for the last statement inefi_boot_kernel().OK
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hope this series will be stable as soon as possible, our kexec/kdump work needs to adjust because of this change. :)
Do you have a link to those patches?
There is a snapshot for patches pending for 6.1:
https://github.com/loongson/linux/commits/loongarch-nextThanks. I already spotted an issue there which is exactly the kind of thing I am trying to avoid with this series.
arch/loongarch/kernel/mem.c +5
-0@@ -61,4 +62,9 @@ void __init memblock_init(void)/* Reserve the initrd */ reserve_initrd_mem (); + +/* Main reserved memory for the elf core head */ +early_init_fdt_scan_reserved_mem (); +/* Parse linux,usable-memory-range for crash dump kernel */ +early_init_dt_check_for_usable_mem_range (); }So here, we are adding support for DT memory reservations, which kdump apparently needs.
However, this parsing of the DT not only happens on kexec boot: all ACPI and DT kernels will now honour FDT memory reservations passed in via a DT when booting the first kernel, and external projects may use this and start to depend on this.
Quoted 6 lines
Once something like this hits the upstream kernel, it is *very* difficult to change or remove.
If you only need to pass the usable memory range for kcrash/kdump, it's probably better to use a command line option for that, instead of relying on DT memory reservations.
Thank you for your suggestion, but we found some trouble when handle initrd in kexec.
In current implementation, we generate a fdt in kexec-tools, then fill "linux,usable-memory-range", "linux,elfcorehdr" and initrd information in it. After this series, we can use "mem=xxx" "elfcorehdr=" in cmdline, but how to handle initrd information which is stored in a system table?Quoted 5 lines
Quoted 2 lines
There are two options:
- use initrdmem= on the command lineThis is not a good way, even if the second kernel handle "initrdmem=", it will conflict with the config table.
It will not conflict - initrdmem= supersedes the INITRD table because early param passing happens after
efi_init().Quoted 5 lines
Quoted 2 lines
- update the INITRD config table in memory (i.e., update the base and size to refer to the new initrd image)
This way seems practicable, but we don't know how to handle it in kexec-tools. :(
Quoted 7 lines
Quoted 1 line
Good point. Let me think a bit about this.
OK, then let's go back to this series itself. :)
I have seen the latest code in your git repo, I don't think we need
efi_disable_rt. Instead, setting/clearingEFI_BOOTaccording to a0 as before seems reasonable.No, not really.
EFI_BOOTbasically means 'did I boot via EFI?' and strictly, you should not be attempting to access the EFI system table or parse EFI config tables unlessEFI_BOOTis true.Deviating from this makes it more difficult for generic code to reason about what parts of EFI are active on a given system.
Quoted 4 lines
If
efi_novamapbreaks something, I can accept "setefi_novamapto false" in the previous version, or just ignore its value in the efistub, but a0 should clearly be the indicator ofEFI_BOOT.
Quoted 7 lines
I'm fine with keeping
efi_novamapif you think it has a value. To me, it seems rather pointless, because it prevents you from using the runtime services.If you want a0 to control the EFI boot flag, you should find another way to control whether runtime services can be used, because they are really two different things.
I'm very sorry, after an offline discussion with my colleagues, non-EFI DT boot is still needed (very sadly, we want to drop non-EFI firmware but we can't do that). However, for non-EFI DT boot we will use the same parameter passing method (a0=efi boot flag, a1=cmdline, a2=systemtable), firmware will generate a simple systemtable only for DT. In this way all boot methods share the same logic, and also make kexec easy to implement.
So, let's make a0 the real "efi boot flag" and let it control EFI_BOOT, for efistub, we can just pass "true" unconditionally (whether support efi_novamap is not as important as the efi boot flag for us, as you said, efi_novamap is just for broken firmware).
Huacai
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 3 lines · Huacai Chen
Hi, Ard,
...
Quoted 8 lines
I'm very sorry, after an offline discussion with my colleagues, non-EFI DT boot is still needed (very sadly, we want to drop non-EFI firmware but we can't do that). However, for non-EFI DT boot we will use the same parameter passing method (a0=efi boot flag, a1=cmdline, a2=systemtable), firmware will generate a simple systemtable only for DT. In this way all boot methods share the same logic, and also make kexec easy to implement.
OK, that should work. So I suppose you create a EFI system table along with EFI configuration tables for DT, SMBIOS, etc? In this case, I suggest you omit the MEMMAP config table that I am adding here, so that there is no ambiguity between the EFI provided memory map and the one provided by DT.
I think that should be a clean way to implement this.
Quoted 4 lines
So, let's make a0 the real "efi boot flag" and let it control
EFI_BOOT, for efistub, we can just pass "true" unconditionally (whether supportefi_novamapis not as important as the efi boot flag for us, as you said,efi_novamapis just for broken firmware).
Indeed. So as before, I will just set efi_novamap to false. You can still use noefi or efi=noruntime to turn off the EFI runtime pieces if needed (e.g., PREEMPT_RT tends to disable those by default to preserve their bounded worst case latency)
Huacai Chen
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Hi, Ard,
Quoted 15 lines · Ard Biesheuvel
Quoted 3 lines · Huacai Chen
Hi, Ard,
...
Quoted 8 lines
I'm very sorry, after an offline discussion with my colleagues, non-EFI DT boot is still needed (very sadly, we want to drop non-EFI firmware but we can't do that). However, for non-EFI DT boot we will use the same parameter passing method (a0=efi boot flag, a1=cmdline, a2=systemtable), firmware will generate a simple systemtable only for DT. In this way all boot methods share the same logic, and also make kexec easy to implement.
Quoted 7 lines
OK, that should work. So I suppose you create a EFI system table along with EFI configuration tables for DT, SMBIOS, etc? In this case, I suggest you omit the MEMMAP config table that I am adding here, so that there is no ambiguity between the EFI provided memory map and the one provided by DT.
I think that should be a clean way to implement this.
OK, thanks.
I have merged efi-cleanups-for-v6.1-v2 to
https://github.com/loongson/linux/commits/loongarch-next. It seems everything work well except kexec.
Huacai
Quoted 10 lines
Quoted 5 lines
So, let's make a0 the real "efi boot flag" and let it control
EFI_BOOT, for efistub, we can just pass "true" unconditionally (whether supportefi_novamapis not as important as the efi boot flag for us, as you said,efi_novamapis just for broken firmware).Indeed. So as before, I will just set
efi_novamapto false. You can still use noefi or efi=noruntime to turn off the EFI runtime pieces if needed (e.g.,PREEMPT_RTtends to disable those by default to preserve their bounded worst case latency)
Ard Biesheuvel
maintainerRe: [PATCH 11/12] efi/loongarch: libstub: remove dependency on flattened DT
Quoted 25 lines · Huacai Chen
Hi, Ard,
Quoted 21 lines · Ard Biesheuvel
Quoted 3 lines · Huacai Chen
Hi, Ard,
...
Quoted 8 lines
I'm very sorry, after an offline discussion with my colleagues, non-EFI DT boot is still needed (very sadly, we want to drop non-EFI firmware but we can't do that). However, for non-EFI DT boot we will use the same parameter passing method (a0=efi boot flag, a1=cmdline, a2=systemtable), firmware will generate a simple systemtable only for DT. In this way all boot methods share the same logic, and also make kexec easy to implement.
OK, that should work. So I suppose you create a EFI system table along with EFI configuration tables for DT, SMBIOS, etc? In this case, I suggest you omit the MEMMAP config table that I am adding here, so that there is no ambiguity between the EFI provided memory map and the one provided by DT.
Quoted 7 lines
Quoted 1 line
I think that should be a clean way to implement this.
OK, thanks.
I have merged efi-cleanups-for-v6.1-v2 to
https://github.com/loongson/linux/commits/loongarch-next. It seems everything work well except kexec.
OK thanks for testing. I will send out a v2 today and merge the changes into efi/next tomorrow.
Ard Biesheuvel
maintainerPATCH 12/12 efi: loongarch: add support for DT hardware descriptions
In reply to Ard BiesheuvelTreat device tree data in the same way as we treat ACPI tables: discover them from the EFI configuration table array, and parse the properties that describe hardware. This means we omit /chosen and the /memory nodes, which carry information that we should be receiving from EFI. not from the device tree.
On the non-EFI boot path, parse the DT passed via the boot entrypoint as
usual: things like bootargs, initrd and other bootloader generated data are all loaded from the DT /chosen node, along with memory descriptions and other things we would otherwise get from EFI.
Note that this approach is similar to x86, which also supports FDT for hardware descriptions but not for boottime generated data.
--- arch/loongarch/Kconfig | 2 ++ arch/loongarch/kernel/efi.c | 14 ++++++++++++++ arch/loongarch/kernel/env.c | 6 ++++++ 3 files changed, 22 insertions(+)
arch/loongarch/Kconfig +2 -0
@@ -104,6 +104,8 @@ config LOONGARCH select MODULES_USE_ELF_RELA if MODULES select NEED_PER_CPU_EMBED_FIRST_CHUNK select NEED_PER_CPU_PAGE_FIRST_CHUNK + select OF + select OF_EARLY_FLATTREE select PCI select PCI_DOMAINS_GENERIC select PCI_ECAM if ACPI
arch/loongarch/kernel/efi.c +14 -0
@@ -17,6 +17,7 @@#include <linux/io.h> #include <linux/kobject.h> #include <linux/memblock.h> +#include <linux/of_fdt.h> #include <linux/reboot.h> #include <linux/uaccess.h>
@@ -28,10 +29,12 @@ static unsigned long efi_nr_tables;static unsigned long efi_config_table;static unsigned long __initdata boot_memmap =EFI_INVALID_TABLE_ADDR ; +static unsigned long __initdata boot_fdt =EFI_INVALID_TABLE_ADDR ;static efi_system_table_t *efi_systab;static efi_config_table_type_t arch_tables[]__initdata = { {LINUX_EFI_BOOT_MEMMAP_GUID , &boot_memmap,"MEMMAP" }, + {DEVICE_TREE_GUID , &boot_fdt,"FDT" }, {}, };
@@ -100,4 +103,15 @@ void __init efi_init(void)early_memunmap (tbl,sizeof (*tbl)); } } + +if (boot_fdt !=EFI_INVALID_TABLE_ADDR ) { +void *tbl; + + tbl =early_memremap_ro (boot_fdt,sizeof (*tbl)); +if (tbl) { +early_init_dt_verify (tbl); +early_init_dt_scan_root (); +early_init_fdt_reserve_self (); + } + } }
arch/loongarch/kernel/env.c +6 -0
@@ -8,6 +8,7 @@#include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> +#include <linux/of_fdt.h> #include <asm/early_ioremap.h> #include <asm/bootinfo.h> #include <asm/loongson.h>
@@ -29,6 +30,11 @@ void __init init_environ(void) efi_system_table = fw_arg1;set_bit (EFI_BOOT , &efi.flags); }else { +void *fdt_ptr =early_memremap_ro (fw_arg1,SZ_64K ); + +early_init_dt_scan (fdt_ptr); +early_init_fdt_reserve_self (); +clear_bit (EFI_BOOT , &efi.flags); } }
Signature · 1 line
2.35.1