Tom Rini | 10e4779 | 2018-05-06 17:58:06 -0400 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 4 | */ |
| 5 | |
Simon Glass | f92c54e | 2025-03-15 14:25:53 +0000 | [diff] [blame] | 6 | #define LOG_CATEGORY LOGC_ARCH |
| 7 | |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 8 | #include <efi_loader.h> |
Sughosh Ganu | 526eebd | 2024-10-15 21:07:13 +0530 | [diff] [blame] | 9 | #include <lmb.h> |
Simon Glass | f92c54e | 2025-03-15 14:25:53 +0000 | [diff] [blame] | 10 | #include <log.h> |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 11 | #include <asm/e820.h> |
Simon Glass | 3ba929a | 2020-10-30 21:38:53 -0600 | [diff] [blame] | 12 | #include <asm/global_data.h> |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 13 | |
| 14 | DECLARE_GLOBAL_DATA_PTR; |
| 15 | |
Simon Glass | b106f07 | 2025-03-15 14:25:52 +0000 | [diff] [blame] | 16 | static const char *const e820_type_name[E820_COUNT] = { |
| 17 | [E820_RAM] = "RAM", |
| 18 | [E820_RESERVED] = "Reserved", |
| 19 | [E820_ACPI] = "ACPI", |
| 20 | [E820_NVS] = "ACPI NVS", |
| 21 | [E820_UNUSABLE] = "Unusable", |
| 22 | }; |
| 23 | |
| 24 | void e820_dump(struct e820_entry *entries, uint count) |
| 25 | { |
| 26 | int i; |
| 27 | |
| 28 | printf("%12s %10s %s\n", "Addr", "Size", "Type"); |
| 29 | for (i = 0; i < count; i++) { |
| 30 | struct e820_entry *entry = &entries[i]; |
| 31 | |
| 32 | printf("%12llx %10llx %s\n", entry->addr, entry->size, |
| 33 | entry->type < E820_COUNT ? |
| 34 | e820_type_name[entry->type] : |
| 35 | simple_itoa(entry->type)); |
| 36 | } |
| 37 | } |
| 38 | |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 39 | /* |
| 40 | * Install a default e820 table with 4 entries as follows: |
| 41 | * |
| 42 | * 0x000000-0x0a0000 Useable RAM |
| 43 | * 0x0a0000-0x100000 Reserved for ISA |
| 44 | * 0x100000-gd->ram_size Useable RAM |
| 45 | * CONFIG_PCIE_ECAM_BASE PCIe ECAM |
| 46 | */ |
Bin Meng | 3838d71 | 2018-04-11 22:02:10 -0700 | [diff] [blame] | 47 | __weak unsigned int install_e820_map(unsigned int max_entries, |
Bin Meng | 4b8fc74 | 2018-04-11 22:02:11 -0700 | [diff] [blame] | 48 | struct e820_entry *entries) |
Bin Meng | a489963 | 2015-10-07 20:19:10 -0700 | [diff] [blame] | 49 | { |
| 50 | entries[0].addr = 0; |
| 51 | entries[0].size = ISA_START_ADDRESS; |
| 52 | entries[0].type = E820_RAM; |
| 53 | entries[1].addr = ISA_START_ADDRESS; |
| 54 | entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS; |
| 55 | entries[1].type = E820_RESERVED; |
| 56 | entries[2].addr = ISA_END_ADDRESS; |
| 57 | entries[2].size = gd->ram_size - ISA_END_ADDRESS; |
| 58 | entries[2].type = E820_RAM; |
| 59 | entries[3].addr = CONFIG_PCIE_ECAM_BASE; |
| 60 | entries[3].size = CONFIG_PCIE_ECAM_SIZE; |
| 61 | entries[3].type = E820_RESERVED; |
| 62 | |
| 63 | return 4; |
| 64 | } |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 65 | |
Simon Glass | f92c54e | 2025-03-15 14:25:53 +0000 | [diff] [blame] | 66 | void e820_init(struct e820_ctx *ctx, struct e820_entry *entries, |
| 67 | int max_entries) |
| 68 | { |
| 69 | memset(ctx, '\0', sizeof(*ctx)); |
| 70 | ctx->entries = entries; |
| 71 | ctx->max_entries = max_entries; |
| 72 | } |
| 73 | |
| 74 | void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size) |
| 75 | { |
| 76 | struct e820_entry *entry = &ctx->entries[ctx->count++]; |
| 77 | |
| 78 | if (ctx->count <= ctx->max_entries) { |
| 79 | entry->addr = addr; |
| 80 | entry->size = size; |
| 81 | entry->type = type; |
| 82 | } |
| 83 | ctx->addr = addr + size; |
| 84 | } |
| 85 | |
| 86 | void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size) |
| 87 | { |
| 88 | e820_add(ctx, type, ctx->addr, size); |
| 89 | } |
| 90 | |
| 91 | void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 addr) |
| 92 | { |
| 93 | e820_next(ctx, type, addr - ctx->addr); |
| 94 | } |
| 95 | |
| 96 | int e820_finish(struct e820_ctx *ctx) |
| 97 | { |
| 98 | if (ctx->count > ctx->max_entries) { |
| 99 | printf("e820 has %d entries but room for only %d\n", ctx->count, |
| 100 | ctx->max_entries); |
| 101 | panic("e820 table too large"); |
| 102 | } |
| 103 | log_debug("e820 map installed, n=%d\n", ctx->count); |
| 104 | if (_DEBUG) |
| 105 | e820_dump(ctx->entries, ctx->count); |
| 106 | |
| 107 | return ctx->count; |
| 108 | } |
| 109 | |
Stephen Warren | d0de806 | 2018-08-30 15:43:43 -0600 | [diff] [blame] | 110 | #if CONFIG_IS_ENABLED(EFI_LOADER) |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 111 | void efi_add_known_memory(void) |
| 112 | { |
| 113 | struct e820_entry e820[E820MAX]; |
| 114 | unsigned int i, num; |
Sughosh Ganu | 526eebd | 2024-10-15 21:07:13 +0530 | [diff] [blame] | 115 | u64 start; |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 116 | int type; |
| 117 | |
| 118 | num = install_e820_map(ARRAY_SIZE(e820), e820); |
| 119 | |
| 120 | for (i = 0; i < num; ++i) { |
| 121 | start = e820[i].addr; |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 122 | |
| 123 | switch (e820[i].type) { |
| 124 | case E820_RAM: |
| 125 | type = EFI_CONVENTIONAL_MEMORY; |
| 126 | break; |
| 127 | case E820_RESERVED: |
| 128 | type = EFI_RESERVED_MEMORY_TYPE; |
| 129 | break; |
| 130 | case E820_ACPI: |
| 131 | type = EFI_ACPI_RECLAIM_MEMORY; |
| 132 | break; |
| 133 | case E820_NVS: |
| 134 | type = EFI_ACPI_MEMORY_NVS; |
| 135 | break; |
| 136 | case E820_UNUSABLE: |
| 137 | default: |
| 138 | type = EFI_UNUSABLE_MEMORY; |
| 139 | break; |
| 140 | } |
| 141 | |
Sughosh Ganu | 526eebd | 2024-10-15 21:07:13 +0530 | [diff] [blame] | 142 | if (type != EFI_CONVENTIONAL_MEMORY) |
Michael Walle | 282d386 | 2020-05-17 12:29:19 +0200 | [diff] [blame] | 143 | efi_add_memory_map(start, e820[i].size, type); |
Bin Meng | 1a4e82d | 2018-06-27 20:38:01 -0700 | [diff] [blame] | 144 | } |
| 145 | } |
Stephen Warren | d0de806 | 2018-08-30 15:43:43 -0600 | [diff] [blame] | 146 | #endif /* CONFIG_IS_ENABLED(EFI_LOADER) */ |
Sughosh Ganu | 526eebd | 2024-10-15 21:07:13 +0530 | [diff] [blame] | 147 | |
| 148 | #if CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP) |
| 149 | void lmb_arch_add_memory(void) |
| 150 | { |
| 151 | struct e820_entry e820[E820MAX]; |
| 152 | unsigned int i, num; |
| 153 | u64 ram_top; |
| 154 | |
| 155 | num = install_e820_map(ARRAY_SIZE(e820), e820); |
| 156 | |
| 157 | ram_top = (u64)gd->ram_top & ~EFI_PAGE_MASK; |
| 158 | if (!ram_top) |
| 159 | ram_top = 0x100000000ULL; |
| 160 | |
| 161 | for (i = 0; i < num; ++i) { |
| 162 | if (e820[i].type == E820_RAM) { |
| 163 | u64 start, size, rgn_top; |
| 164 | |
| 165 | start = e820[i].addr; |
| 166 | size = e820[i].size; |
| 167 | rgn_top = start + size; |
| 168 | |
| 169 | if (start > ram_top) |
| 170 | continue; |
| 171 | |
| 172 | if (rgn_top > ram_top) |
| 173 | size -= rgn_top - ram_top; |
| 174 | |
| 175 | lmb_add(start, size); |
| 176 | } |
| 177 | } |
| 178 | } |
| 179 | #endif /* CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP) */ |