0001
0002 #define BOOT_CTYPE_H
0003 #include "misc.h"
0004 #include "error.h"
0005 #include "../string.h"
0006 #include "efi.h"
0007
0008 #include <linux/numa.h>
0009
0010
0011
0012
0013
0014 #define MAX_ACPI_ARG_LENGTH 10
0015
0016
0017
0018
0019
0020 struct mem_vector immovable_mem[MAX_NUMNODES*2];
0021
0022 static acpi_physical_address
0023 __efi_get_rsdp_addr(unsigned long cfg_tbl_pa, unsigned int cfg_tbl_len)
0024 {
0025 #ifdef CONFIG_EFI
0026 unsigned long rsdp_addr;
0027 int ret;
0028
0029
0030
0031
0032
0033 rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len,
0034 ACPI_20_TABLE_GUID);
0035 if (rsdp_addr)
0036 return (acpi_physical_address)rsdp_addr;
0037
0038
0039 rsdp_addr = efi_find_vendor_table(boot_params, cfg_tbl_pa, cfg_tbl_len,
0040 ACPI_TABLE_GUID);
0041 if (rsdp_addr)
0042 return (acpi_physical_address)rsdp_addr;
0043
0044 debug_putstr("Error getting RSDP address.\n");
0045 #endif
0046 return 0;
0047 }
0048
0049 static acpi_physical_address efi_get_rsdp_addr(void)
0050 {
0051 #ifdef CONFIG_EFI
0052 unsigned long cfg_tbl_pa = 0;
0053 unsigned int cfg_tbl_len;
0054 unsigned long systab_pa;
0055 unsigned int nr_tables;
0056 enum efi_type et;
0057 int ret;
0058
0059 et = efi_get_type(boot_params);
0060 if (et == EFI_TYPE_NONE)
0061 return 0;
0062
0063 systab_pa = efi_get_system_table(boot_params);
0064 if (!systab_pa)
0065 error("EFI support advertised, but unable to locate system table.");
0066
0067 ret = efi_get_conf_table(boot_params, &cfg_tbl_pa, &cfg_tbl_len);
0068 if (ret || !cfg_tbl_pa)
0069 error("EFI config table not found.");
0070
0071 return __efi_get_rsdp_addr(cfg_tbl_pa, cfg_tbl_len);
0072 #else
0073 return 0;
0074 #endif
0075 }
0076
0077 static u8 compute_checksum(u8 *buffer, u32 length)
0078 {
0079 u8 *end = buffer + length;
0080 u8 sum = 0;
0081
0082 while (buffer < end)
0083 sum += *(buffer++);
0084
0085 return sum;
0086 }
0087
0088
0089 static u8 *scan_mem_for_rsdp(u8 *start, u32 length)
0090 {
0091 struct acpi_table_rsdp *rsdp;
0092 u8 *address, *end;
0093
0094 end = start + length;
0095
0096
0097 for (address = start; address < end; address += ACPI_RSDP_SCAN_STEP) {
0098
0099
0100
0101
0102
0103
0104 rsdp = (struct acpi_table_rsdp *)address;
0105
0106
0107 if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature))
0108 continue;
0109
0110
0111 if (compute_checksum((u8 *)rsdp, ACPI_RSDP_CHECKSUM_LENGTH))
0112 continue;
0113
0114
0115 if ((rsdp->revision >= 2) &&
0116 (compute_checksum((u8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)))
0117 continue;
0118
0119
0120 return address;
0121 }
0122 return NULL;
0123 }
0124
0125
0126 static acpi_physical_address bios_get_rsdp_addr(void)
0127 {
0128 unsigned long address;
0129 u8 *rsdp;
0130
0131
0132 address = *(u16 *)ACPI_EBDA_PTR_LOCATION;
0133 address <<= 4;
0134
0135
0136
0137
0138
0139 if (address > 0x400) {
0140 rsdp = scan_mem_for_rsdp((u8 *)address, ACPI_EBDA_WINDOW_SIZE);
0141 if (rsdp)
0142 return (acpi_physical_address)(unsigned long)rsdp;
0143 }
0144
0145
0146 rsdp = scan_mem_for_rsdp((u8 *) ACPI_HI_RSDP_WINDOW_BASE,
0147 ACPI_HI_RSDP_WINDOW_SIZE);
0148 if (rsdp)
0149 return (acpi_physical_address)(unsigned long)rsdp;
0150
0151 return 0;
0152 }
0153
0154
0155 acpi_physical_address get_rsdp_addr(void)
0156 {
0157 acpi_physical_address pa;
0158
0159 pa = boot_params->acpi_rsdp_addr;
0160
0161 if (!pa)
0162 pa = efi_get_rsdp_addr();
0163
0164 if (!pa)
0165 pa = bios_get_rsdp_addr();
0166
0167 return pa;
0168 }
0169
0170 #if defined(CONFIG_RANDOMIZE_BASE) && defined(CONFIG_MEMORY_HOTREMOVE)
0171
0172
0173
0174
0175 #define MAX_ADDR_LEN 19
0176
0177 static unsigned long get_cmdline_acpi_rsdp(void)
0178 {
0179 unsigned long addr = 0;
0180
0181 #ifdef CONFIG_KEXEC
0182 char val[MAX_ADDR_LEN] = { };
0183 int ret;
0184
0185 ret = cmdline_find_option("acpi_rsdp", val, MAX_ADDR_LEN);
0186 if (ret < 0)
0187 return 0;
0188
0189 if (boot_kstrtoul(val, 16, &addr))
0190 return 0;
0191 #endif
0192 return addr;
0193 }
0194
0195
0196 static unsigned long get_acpi_srat_table(void)
0197 {
0198 unsigned long root_table, acpi_table;
0199 struct acpi_table_header *header;
0200 struct acpi_table_rsdp *rsdp;
0201 u32 num_entries, size, len;
0202 char arg[10];
0203 u8 *entry;
0204
0205
0206
0207
0208
0209
0210 rsdp = (struct acpi_table_rsdp *)get_cmdline_acpi_rsdp();
0211 if (!rsdp)
0212 rsdp = (struct acpi_table_rsdp *)(long)
0213 boot_params->acpi_rsdp_addr;
0214
0215 if (!rsdp)
0216 return 0;
0217
0218
0219 if (!(cmdline_find_option("acpi", arg, sizeof(arg)) == 4 &&
0220 !strncmp(arg, "rsdt", 4)) &&
0221 rsdp->xsdt_physical_address &&
0222 rsdp->revision > 1) {
0223 root_table = rsdp->xsdt_physical_address;
0224 size = ACPI_XSDT_ENTRY_SIZE;
0225 } else {
0226 root_table = rsdp->rsdt_physical_address;
0227 size = ACPI_RSDT_ENTRY_SIZE;
0228 }
0229
0230 if (!root_table)
0231 return 0;
0232
0233 header = (struct acpi_table_header *)root_table;
0234 len = header->length;
0235 if (len < sizeof(struct acpi_table_header) + size)
0236 return 0;
0237
0238 num_entries = (len - sizeof(struct acpi_table_header)) / size;
0239 entry = (u8 *)(root_table + sizeof(struct acpi_table_header));
0240
0241 while (num_entries--) {
0242 if (size == ACPI_RSDT_ENTRY_SIZE)
0243 acpi_table = *(u32 *)entry;
0244 else
0245 acpi_table = *(u64 *)entry;
0246
0247 if (acpi_table) {
0248 header = (struct acpi_table_header *)acpi_table;
0249
0250 if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_SRAT))
0251 return acpi_table;
0252 }
0253 entry += size;
0254 }
0255 return 0;
0256 }
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268 int count_immovable_mem_regions(void)
0269 {
0270 unsigned long table_addr, table_end, table;
0271 struct acpi_subtable_header *sub_table;
0272 struct acpi_table_header *table_header;
0273 char arg[MAX_ACPI_ARG_LENGTH];
0274 int num = 0;
0275
0276 if (cmdline_find_option("acpi", arg, sizeof(arg)) == 3 &&
0277 !strncmp(arg, "off", 3))
0278 return 0;
0279
0280 table_addr = get_acpi_srat_table();
0281 if (!table_addr)
0282 return 0;
0283
0284 table_header = (struct acpi_table_header *)table_addr;
0285 table_end = table_addr + table_header->length;
0286 table = table_addr + sizeof(struct acpi_table_srat);
0287
0288 while (table + sizeof(struct acpi_subtable_header) < table_end) {
0289
0290 sub_table = (struct acpi_subtable_header *)table;
0291 if (!sub_table->length) {
0292 debug_putstr("Invalid zero length SRAT subtable.\n");
0293 return 0;
0294 }
0295
0296 if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
0297 struct acpi_srat_mem_affinity *ma;
0298
0299 ma = (struct acpi_srat_mem_affinity *)sub_table;
0300 if (!(ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) && ma->length) {
0301 immovable_mem[num].start = ma->base_address;
0302 immovable_mem[num].size = ma->length;
0303 num++;
0304 }
0305
0306 if (num >= MAX_NUMNODES*2) {
0307 debug_putstr("Too many immovable memory regions, aborting.\n");
0308 return 0;
0309 }
0310 }
0311 table += sub_table->length;
0312 }
0313 return num;
0314 }
0315 #endif