Skip to content

Commit 42046c2

Browse files
shankerwangmiaoMingcongBai
authored andcommitted
AOSCOS: loongarch: basic boot support for legacy firmware
The addresses passed from legacy firmware in efi system tables, the initrd table, the efi system memory mapping table are virtual addresses. This patch converts all that addresses back to physical addresses, to make sure all the following booting processes can run smoothly like on modern firmwares. The conversion happens unconditionally, since physical addresses passed in by modern firmwares remain unchanged after the conversion. In the EFI Stub, the mapping entries given by GetMemoryMap() on legacy firmwares contain virtual addresses in the phys_addr fields and 0x1xxxx addresses in the virt_addr fields, causing the later call to SetVirtualAddressMap() fails. This patch fixes this by correcting the addresses in the virt_addr fields. This patch detects the existence of the legacy firmware by reading DMW1 CSR, as done in the legacy loongarch GRUB port. Only if legacy firmwares detected, this correction happens. With this patch, the linux kernel is basically able to boot. Signed-off-by: Miao Wang <shankerwangmiao@gmail.com> Signed-off-by: Kexy Biscuit <kexybiscuit@aosc.io> Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
1 parent 12790a1 commit 42046c2

3 files changed

Lines changed: 37 additions & 0 deletions

File tree

arch/loongarch/kernel/efi.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,23 @@ static void __init init_primary_display(void)
9999
sysfb_primary_display.screen.lfb_size);
100100
}
101101

102+
static void __init fix_initrd_table(const efi_config_table_t *config_tables,
103+
int count)
104+
{
105+
for(int i = 0; i < count; i++) {
106+
if (efi_guidcmp(config_tables[i].guid,
107+
LINUX_EFI_INITRD_MEDIA_GUID) == 0) {
108+
struct linux_efi_initrd *tbl =
109+
early_memremap((u64)config_tables[i].table, sizeof(*tbl));
110+
if (tbl) {
111+
tbl->base = TO_PHYS(tbl->base);
112+
early_memunmap(tbl, sizeof(*tbl));
113+
}
114+
break;
115+
}
116+
}
117+
}
118+
102119
void __init efi_init(void)
103120
{
104121
int size;
@@ -124,6 +141,7 @@ void __init efi_init(void)
124141

125142
size = sizeof(efi_config_table_t);
126143
config_tables = early_memremap(efi_config_table, efi_nr_tables * size);
144+
fix_initrd_table(config_tables, efi_systab->nr_tables);
127145
efi_config_parse_tables(config_tables, efi_systab->nr_tables, arch_tables);
128146
early_memunmap(config_tables, efi_nr_tables * size);
129147

arch/loongarch/kernel/mem.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ void __init memblock_init(void)
1919
/* Parse memory information */
2020
for_each_efi_memory_desc(md) {
2121
mem_type = md->type;
22+
md->phys_addr = TO_PHYS(md->phys_addr);
2223
mem_start = md->phys_addr;
2324
mem_size = md->num_pages << EFI_PAGE_SHIFT;
2425

drivers/firmware/efi/libstub/loongarch.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct exit_boot_struct {
4444
int runtime_entry_count;
4545
};
4646

47+
static int is_oldworld = 0;
48+
4749
static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
4850
{
4951
struct exit_boot_struct *p = priv;
@@ -59,6 +61,15 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
5961
return EFI_SUCCESS;
6062
}
6163

64+
static void detect_oldworld(void)
65+
{
66+
is_oldworld = !!(csr_read64(LOONGARCH_CSR_DMWIN1) & CSR_DMW1_PLV0);
67+
efi_debug("is_oldworld: %d\n", is_oldworld);
68+
if(is_oldworld) {
69+
efi_info("Booting on OldWorld firmware\n");
70+
}
71+
}
72+
6273
unsigned long __weak kernel_entry_address(unsigned long kernel_addr,
6374
efi_loaded_image_t *image)
6475
{
@@ -74,6 +85,8 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
7485
efi_status_t status;
7586
u32 desc_ver;
7687

88+
detect_oldworld();
89+
7790
status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver);
7891
if (status != EFI_SUCCESS) {
7992
efi_err("Unable to retrieve UEFI memory map.\n");
@@ -87,11 +100,16 @@ efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
87100
if (status != EFI_SUCCESS)
88101
return status;
89102

103+
if (is_oldworld) {
104+
goto skip_set_virtual_address_map;
105+
}
106+
90107
/* Install the new virtual address map */
91108
efi_rt_call(set_virtual_address_map,
92109
priv.runtime_entry_count * desc_size, desc_size,
93110
desc_ver, priv.runtime_map);
94111

112+
skip_set_virtual_address_map:
95113
/* Config Direct Mapping */
96114
csr_write(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
97115
csr_write(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);

0 commit comments

Comments
 (0)