1 /* $OpenBSD: efiacpi.c,v 1.5 2018/08/11 16:02:33 kettenis Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 21 #include <efi.h> 22 #include <efiapi.h> 23 24 #include "eficall.h" 25 #include "fdt.h" 26 #include "libsa.h" 27 28 #define efi_guidcmp(_a, _b) memcmp((_a), (_b), sizeof(EFI_GUID)) 29 30 #define fdt_node_add_string_property(n, p, s) \ 31 fdt_node_add_property((n), (p), (s), strlen((s)) + 1) 32 #define fdt_node_set_string_property(n, p, s) \ 33 fdt_node_set_property((n), (p), (s), strlen((s)) + 1) 34 35 extern EFI_SYSTEM_TABLE *ST; 36 37 /* ACPI tables */ 38 39 struct acpi_rsdp1 { 40 uint8_t signature[8]; 41 #define RSDP_SIG "RSD PTR " 42 #define rsdp_signature rsdp1.signature 43 uint8_t checksum; /* make sum == 0 */ 44 #define rsdp_checksum rsdp1.checksum 45 uint8_t oemid[6]; 46 #define rsdp_oemid rsdp1.oemid 47 uint8_t revision; /* 0 for 1, 2 for 2 */ 48 #define rsdp_revision rsdp1.revision 49 uint32_t rsdt; /* physical */ 50 #define rsdp_rsdt rsdp1.rsdt 51 } __packed; 52 53 struct acpi_rsdp { 54 struct acpi_rsdp1 rsdp1; 55 /* 56 * The following values are only valid 57 * when rsdp_revision == 2 58 */ 59 uint32_t rsdp_length; /* length of rsdp */ 60 uint64_t rsdp_xsdt; /* physical */ 61 uint8_t rsdp_extchecksum; /* entire table */ 62 uint8_t rsdp_reserved[3]; /* must be zero */ 63 } __packed; 64 65 struct acpi_table_header { 66 uint8_t signature[4]; 67 #define hdr_signature hdr.signature 68 uint32_t length; 69 #define hdr_length hdr.length 70 uint8_t revision; 71 #define hdr_revision hdr.revision 72 uint8_t checksum; 73 #define hdr_checksum hdr.checksum 74 uint8_t oemid[6]; 75 #define hdr_oemid hdr.oemid 76 uint8_t oemtableid[8]; 77 #define hdr_oemtableid hdr.oemtableid 78 uint32_t oemrevision; 79 #define hdr_oemrevision hdr.oemrevision 80 uint8_t aslcompilerid[4]; 81 #define hdr_aslcompilerid hdr.aslcompilerid 82 uint32_t aslcompilerrevision; 83 #define hdr_aslcompilerrevision hdr.aslcompilerrevision 84 } __packed; 85 86 struct acpi_xsdt { 87 struct acpi_table_header hdr; 88 #define XSDT_SIG "XSDT" 89 uint64_t table_offsets[1]; 90 } __packed; 91 92 struct acpi_gas { 93 uint8_t address_space_id; 94 #define GAS_SYSTEM_MEMORY 0 95 #define GAS_SYSTEM_IOSPACE 1 96 #define GAS_PCI_CFG_SPACE 2 97 #define GAS_EMBEDDED 3 98 #define GAS_SMBUS 4 99 #define GAS_FUNCTIONAL_FIXED 127 100 uint8_t register_bit_width; 101 uint8_t register_bit_offset; 102 uint8_t access_size; 103 #define GAS_ACCESS_UNDEFINED 0 104 #define GAS_ACCESS_BYTE 1 105 #define GAS_ACCESS_WORD 2 106 #define GAS_ACCESS_DWORD 3 107 #define GAS_ACCESS_QWORD 4 108 uint64_t address; 109 } __packed; 110 111 struct acpi_fadt { 112 struct acpi_table_header hdr; 113 #define FADT_SIG "FACP" 114 uint32_t firmware_ctl; /* phys addr FACS */ 115 uint32_t dsdt; /* phys addr DSDT */ 116 uint8_t int_model; /* interrupt model (hdr_revision < 3) */ 117 #define FADT_INT_DUAL_PIC 0 118 #define FADT_INT_MULTI_APIC 1 119 uint8_t pm_profile; /* power mgmt profile */ 120 #define FADT_PM_UNSPEC 0 121 #define FADT_PM_DESKTOP 1 122 #define FADT_PM_MOBILE 2 123 #define FADT_PM_WORKSTATION 3 124 #define FADT_PM_ENT_SERVER 4 125 #define FADT_PM_SOHO_SERVER 5 126 #define FADT_PM_APPLIANCE 6 127 #define FADT_PM_PERF_SERVER 7 128 uint16_t sci_int; /* SCI interrupt */ 129 uint32_t smi_cmd; /* SMI command port */ 130 uint8_t acpi_enable; /* value to enable */ 131 uint8_t acpi_disable; /* value to disable */ 132 uint8_t s4bios_req; /* value for S4 */ 133 uint8_t pstate_cnt; /* value for performance (hdr_revision > 2) */ 134 uint32_t pm1a_evt_blk; /* power management 1a */ 135 uint32_t pm1b_evt_blk; /* power mangement 1b */ 136 uint32_t pm1a_cnt_blk; /* pm control 1a */ 137 uint32_t pm1b_cnt_blk; /* pm control 1b */ 138 uint32_t pm2_cnt_blk; /* pm control 2 */ 139 uint32_t pm_tmr_blk; 140 uint32_t gpe0_blk; 141 uint32_t gpe1_blk; 142 uint8_t pm1_evt_len; 143 uint8_t pm1_cnt_len; 144 uint8_t pm2_cnt_len; 145 uint8_t pm_tmr_len; 146 uint8_t gpe0_blk_len; 147 uint8_t gpe1_blk_len; 148 uint8_t gpe1_base; 149 uint8_t cst_cnt; /* (hdr_revision > 2) */ 150 uint16_t p_lvl2_lat; 151 uint16_t p_lvl3_lat; 152 uint16_t flush_size; 153 uint16_t flush_stride; 154 uint8_t duty_offset; 155 uint8_t duty_width; 156 uint8_t day_alrm; 157 uint8_t mon_alrm; 158 uint8_t century; 159 uint16_t iapc_boot_arch; /* (hdr_revision > 2) */ 160 #define FADT_LEGACY_DEVICES 0x0001 /* Legacy devices supported */ 161 #define FADT_i8042 0x0002 /* Keyboard controller present */ 162 #define FADT_NO_VGA 0x0004 /* Do not probe VGA */ 163 uint8_t reserved1; 164 uint32_t flags; 165 #define FADT_WBINVD 0x00000001 166 #define FADT_WBINVD_FLUSH 0x00000002 167 #define FADT_PROC_C1 0x00000004 168 #define FADT_P_LVL2_UP 0x00000008 169 #define FADT_PWR_BUTTON 0x00000010 170 #define FADT_SLP_BUTTON 0x00000020 171 #define FADT_FIX_RTC 0x00000040 172 #define FADT_RTC_S4 0x00000080 173 #define FADT_TMR_VAL_EXT 0x00000100 174 #define FADT_DCK_CAP 0x00000200 175 #define FADT_RESET_REG_SUP 0x00000400 176 #define FADT_SEALED_CASE 0x00000800 177 #define FADT_HEADLESS 0x00001000 178 #define FADT_CPU_SW_SLP 0x00002000 179 #define FADT_PCI_EXP_WAK 0x00004000 180 #define FADT_USE_PLATFORM_CLOCK 0x00008000 181 #define FADT_S4_RTC_STS_VALID 0x00010000 182 #define FADT_REMOTE_POWER_ON_CAPABLE 0x00020000 183 #define FADT_FORCE_APIC_CLUSTER_MODEL 0x00040000 184 #define FADT_FORCE_APIC_PHYS_DEST_MODE 0x00080000 185 #define FADT_HW_REDUCED_ACPI 0x00100000 186 #define FADT_POWER_S0_IDLE_CAPABLE 0x00200000 187 /* 188 * Following values only exist when rev > 1 189 * If the extended addresses exists, they 190 * must be used in preferense to the non- 191 * extended values above 192 */ 193 struct acpi_gas reset_reg; 194 uint8_t reset_value; 195 uint16_t arm_boot_arch; /* (hdr_revision > 3) */ 196 #define FADT_PSCI_COMPLIANT 0x0001 /* PSCI is implemented */ 197 #define FADT_PSCI_USE_HVC 0x0002 /* HVC used as PSCI conduit */ 198 uint8_t reserved2; 199 uint64_t x_firmware_ctl; 200 uint64_t x_dsdt; 201 struct acpi_gas x_pm1a_evt_blk; 202 struct acpi_gas x_pm1b_evt_blk; 203 struct acpi_gas x_pm1a_cnt_blk; 204 struct acpi_gas x_pm1b_cnt_blk; 205 struct acpi_gas x_pm2_cnt_blk; 206 struct acpi_gas x_pm_tmr_blk; 207 struct acpi_gas x_gpe0_blk; 208 struct acpi_gas x_gpe1_blk; 209 struct acpi_gas sleep_control_reg; 210 struct acpi_gas sleep_status_reg; 211 } __packed; 212 213 struct acpi_gtdt { 214 struct acpi_table_header hdr; 215 #define GTDT_SIG "GTDT" 216 uint64_t cnt_ctrl_base; 217 uint32_t reserved; 218 uint32_t sec_el1_interrupt; 219 uint32_t sec_el1_flags; 220 #define ACPI_GTDT_TIMER_TRIGGER_EDGE 0x1 221 #define ACPI_GTDT_TIMER_POLARITY_LOW 0x2 222 #define ACPI_GTDT_TIMER_ALWAYS_ON 0x4 223 uint32_t nonsec_el1_interrupt; 224 uint32_t nonsec_el1_flags; 225 uint32_t virt_interrupt; 226 uint32_t virt_flags; 227 uint32_t nonsec_el2_interrupt; 228 uint32_t nonsec_el2_flags; 229 uint64_t cnt_read_base; 230 uint32_t platform_timer_count; 231 uint32_t plaform_timer_offset; 232 } __packed; 233 234 struct acpi_madt { 235 struct acpi_table_header hdr; 236 #define MADT_SIG "APIC" 237 uint32_t local_apic_address; 238 uint32_t flags; 239 #define ACPI_APIC_PCAT_COMPAT 0x00000001 240 } __packed; 241 242 struct acpi_madt_gicc { 243 uint8_t apic_type; 244 #define ACPI_MADT_GICC 11 245 uint8_t length; 246 uint16_t reserved1; 247 uint32_t gic_id; 248 uint32_t acpi_proc_uid; 249 uint32_t flags; 250 #define ACPI_PROC_ENABLE 0x00000001 251 uint32_t parking_protocol_version; 252 uint32_t performance_interrupt; 253 uint64_t parked_address; 254 uint64_t base_address; 255 uint64_t gicv_base_address; 256 uint64_t gich_base_address; 257 uint32_t maintenance_interrupt; 258 uint64_t gicr_base_address; 259 uint64_t mpidr; 260 uint8_t efficiency_class; 261 uint8_t reserved2[3]; 262 } __packed; 263 264 struct acpi_madt_gicd { 265 uint8_t apic_type; 266 #define ACPI_MADT_GICD 12 267 uint8_t length; 268 uint16_t reserved1; 269 uint32_t gic_id; 270 uint64_t base_address; 271 uint32_t interrupt_base; 272 uint8_t version; 273 uint8_t reserved2[3]; 274 } __packed; 275 276 struct acpi_madt_gic_msi { 277 uint8_t apic_type; 278 #define ACPI_MADT_GIC_MSI 13 279 uint8_t length; 280 uint16_t reserved1; 281 uint32_t msi_frame_id; 282 uint64_t base_address; 283 uint32_t flags; 284 #define ACPI_MADT_GIC_MSI_SPI_SELECT 0x00000001 285 uint16_t spi_count; 286 uint16_t spi_base; 287 } __packed; 288 289 struct acpi_madt_gicr { 290 uint8_t apic_type; 291 #define ACPI_MADT_GICR 14 292 uint8_t length; 293 uint16_t reserved1; 294 uint64_t discovery_base_address; 295 uint32_t discovery_length; 296 } __packed; 297 298 struct acpi_madt_gic_its { 299 uint8_t apic_type; 300 #define ACPI_MADT_GIC_ITS 15 301 uint8_t length; 302 uint16_t reserved1; 303 uint32_t gic_its_id; 304 uint64_t base_address; 305 uint32_t reserved2; 306 } __packed; 307 308 union acpi_madt_entry { 309 struct acpi_madt_gicc madt_gicc; 310 struct acpi_madt_gicd madt_gicd; 311 struct acpi_madt_gic_msi madt_gic_msi; 312 struct acpi_madt_gicr madt_gicr; 313 struct acpi_madt_gic_its madt_gic_its; 314 } __packed; 315 316 struct acpi_spcr { 317 struct acpi_table_header hdr; 318 #define SPCR_SIG "SPCR" 319 uint8_t interface_type; 320 #define SPCR_16550 0 321 #define SPCR_16450 1 322 #define SPCR_ARM_PL011 3 323 #define SPCR_ARM_SBSA 14 324 uint8_t reserved1[3]; 325 struct acpi_gas base_address; 326 uint8_t interrupt_type; 327 uint8_t irq; 328 uint32_t gsiv; 329 uint8_t baud_rate; 330 uint8_t parity; 331 uint8_t stop_bits; 332 uint8_t flow_control; 333 uint8_t terminal_type; 334 uint8_t reserved2; 335 uint16_t pci_device_id; 336 uint16_t pci_vendor_id; 337 uint8_t pci_bus; 338 uint8_t pci_device; 339 uint8_t pci_function; 340 uint32_t pci_flags; 341 uint8_t pci_segment; 342 uint32_t reserved3; 343 }; 344 345 /* We'll never see ACPI 1.0 tables on ARM. */ 346 static EFI_GUID acpi_guid = ACPI_20_TABLE_GUID; 347 348 static int psci = 0; 349 350 void 351 efi_acpi_fadt(struct acpi_table_header *hdr) 352 { 353 struct acpi_fadt *fadt = (struct acpi_fadt *)hdr; 354 void *node; 355 356 /* 357 * The PSCI flags were introduced in ACPI 5.1. The relevant 358 * field is set to zero for ACPU 5.0. 359 */ 360 if (fadt->hdr_revision < 5) 361 return; 362 363 psci = fadt->arm_boot_arch & FADT_PSCI_COMPLIANT; 364 365 node = fdt_find_node("/psci"); 366 if (fadt->arm_boot_arch & FADT_PSCI_COMPLIANT) 367 fdt_node_set_string_property(node, "status", "okay"); 368 if (fadt->arm_boot_arch & FADT_PSCI_USE_HVC) 369 fdt_node_set_string_property(node, "method", "hvc"); 370 } 371 372 void 373 efi_acpi_gtdt(struct acpi_table_header *hdr) 374 { 375 struct acpi_gtdt *gtdt = (struct acpi_gtdt *)hdr; 376 const uint32_t map[] = { 0x4, 0x1, 0x8, 0x2 }; 377 const uint32_t mask = ACPI_GTDT_TIMER_TRIGGER_EDGE | 378 ACPI_GTDT_TIMER_POLARITY_LOW; 379 uint32_t interrupts[12]; 380 void *node; 381 382 /* All interrupts are supposed to be PPIs. */ 383 interrupts[0] = htobe32(1); 384 interrupts[1] = htobe32(gtdt->sec_el1_interrupt - 16); 385 interrupts[2] = htobe32(map[gtdt->sec_el1_flags & mask]); 386 interrupts[3] = htobe32(1); 387 interrupts[4] = htobe32(gtdt->nonsec_el1_interrupt - 16); 388 interrupts[5] = htobe32(map[gtdt->nonsec_el1_flags & mask]); 389 interrupts[6] = htobe32(1); 390 interrupts[7] = htobe32(gtdt->virt_interrupt - 16); 391 interrupts[8] = htobe32(map[gtdt->virt_flags & mask]); 392 interrupts[9] = htobe32(1); 393 interrupts[10] = htobe32(gtdt->nonsec_el2_interrupt - 16); 394 interrupts[11] = htobe32(map[gtdt->virt_flags & mask]); 395 396 node = fdt_find_node("/timer"); 397 fdt_node_set_property(node, "interrupts", 398 interrupts, sizeof(interrupts)); 399 fdt_node_set_string_property(node, "status", "okay"); 400 } 401 402 static int gic_version; 403 static uint64_t gicc_base; 404 static uint64_t gicd_base; 405 static uint64_t gicr_base; 406 static uint32_t gicr_size; 407 408 void 409 efi_acpi_madt_gicc(struct acpi_madt_gicc *gicc) 410 { 411 uint64_t mpidr = gicc->mpidr; 412 void *node, *child; 413 uint64_t reg; 414 char name[32]; 415 416 /* 417 * MPIDR field was introduced in ACPI 5.1. Fall back on the 418 * ACPI Processor UID on ACPI 5.0. 419 */ 420 mpidr = (gicc->length >= 76) ? gicc->mpidr : gicc->acpi_proc_uid; 421 422 snprintf(name, sizeof(name), "cpu@%llx", mpidr); 423 reg = htobe64(mpidr); 424 425 /* Create "cpu" node. */ 426 node = fdt_find_node("/cpus"); 427 fdt_node_add_node(node, name, &child); 428 fdt_node_add_string_property(child, "device_type", "cpu"); 429 fdt_node_add_string_property(child, "compatible", "arm,armv8"); 430 fdt_node_add_property(child, "reg", ®, sizeof(reg)); 431 if (gicc->parking_protocol_version == 0 || psci) 432 fdt_node_add_string_property(child, "enable-method", "psci"); 433 if ((gicc->flags & ACPI_PROC_ENABLE) == 0) 434 fdt_node_add_string_property(child, "status", "disabled"); 435 436 /* Stash GIC information. */ 437 gicc_base = gicc->base_address; 438 } 439 440 void 441 efi_acpi_madt_gicd(struct acpi_madt_gicd *gicd) 442 { 443 /* Stash GIC information. */ 444 gic_version = gicd->version; 445 gicd_base = gicd->base_address; 446 } 447 448 void 449 efi_acpi_madt_gic_msi(struct acpi_madt_gic_msi *msi) 450 { 451 static uint32_t phandle = 2; 452 void *node, *child; 453 uint64_t reg[2]; 454 char name[32]; 455 456 snprintf(name, sizeof(name), "v2m@%llx", msi->base_address); 457 reg[0] = htobe64(msi->base_address); 458 reg[1] = htobe64(0x1000); 459 460 /* Create "v2m" node. */ 461 node = fdt_find_node("/interrupt-controller"); 462 fdt_node_add_node(node, name, &child); 463 fdt_node_add_string_property(child, "compatible", "arm,gic-v2m-frame"); 464 fdt_node_add_property(child, "msi-controller", NULL, 0); 465 fdt_node_add_property(child, "reg", reg, sizeof(reg)); 466 if (msi->flags & ACPI_MADT_GIC_MSI_SPI_SELECT) { 467 uint32_t spi_base = msi->spi_base; 468 uint32_t spi_count = msi->spi_count; 469 470 fdt_node_add_property(child, "arm,msi-base-spi", 471 &spi_base, sizeof(spi_base)); 472 fdt_node_add_property(child, "arm,msi-num-spis", 473 &spi_count, sizeof(spi_count)); 474 } 475 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle)); 476 phandle++; 477 } 478 479 void 480 efi_acpi_madt_gicr(struct acpi_madt_gicr *gicr) 481 { 482 /* Stash GIC information. */ 483 gicr_base = gicr->discovery_base_address; 484 gicr_size = gicr->discovery_length; 485 } 486 487 void 488 efi_acpi_madt_gic_its(struct acpi_madt_gic_its *its) 489 { 490 static uint32_t phandle = 2; 491 void *node, *child; 492 uint64_t reg[2]; 493 char name[32]; 494 495 snprintf(name, sizeof(name), "gic-its@%llx", its->base_address); 496 reg[0] = htobe64(its->base_address); 497 reg[1] = htobe64(0x20000); 498 499 /* Create "gic-its" node. */ 500 node = fdt_find_node("/interrupt-controller"); 501 fdt_node_add_node(node, name, &child); 502 fdt_node_add_string_property(child, "compatible", "arm,gic-v3-its"); 503 fdt_node_add_property(child, "msi-controller", NULL, 0); 504 fdt_node_add_property(child, "reg", reg, sizeof(reg)); 505 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle)); 506 phandle++; 507 } 508 509 void 510 efi_acpi_madt(struct acpi_table_header *hdr) 511 { 512 struct acpi_madt *madt = (struct acpi_madt *)hdr; 513 char *compat; 514 uint64_t reg[4]; 515 char *addr; 516 void *node; 517 518 /* GIC support was introduced in ACPI 5.0. */ 519 if (madt->hdr_revision < 3) 520 return; 521 522 addr = (char *)(madt + 1); 523 while (addr < (char *)madt + madt->hdr.length) { 524 union acpi_madt_entry *entry = (union acpi_madt_entry *)addr; 525 uint8_t length = entry->madt_gicc.length; 526 527 if (length < 2) 528 return; 529 530 if (addr + length > (char *)madt + madt->hdr_length) 531 return; 532 533 switch (entry->madt_gicc.apic_type) { 534 case ACPI_MADT_GICC: 535 efi_acpi_madt_gicc(&entry->madt_gicc); 536 break; 537 case ACPI_MADT_GICD: 538 efi_acpi_madt_gicd(&entry->madt_gicd); 539 break; 540 case ACPI_MADT_GIC_MSI: 541 efi_acpi_madt_gic_msi(&entry->madt_gic_msi); 542 break; 543 case ACPI_MADT_GICR: 544 efi_acpi_madt_gicr(&entry->madt_gicr); 545 break; 546 case ACPI_MADT_GIC_ITS: 547 efi_acpi_madt_gic_its(&entry->madt_gic_its); 548 break; 549 } 550 551 addr += length; 552 } 553 554 /* 555 * Now that we've collected all the necessary information, fix 556 * up the "interrupt-controller" node. 557 */ 558 559 switch (gic_version) { 560 case 0: 561 /* ACPI 5.0 doesn't provide a version; assume GICv2 */ 562 case 2: 563 /* GICv2 */ 564 compat = "arm,gic-400"; 565 reg[0] = htobe64(gicd_base); 566 reg[1] = htobe64(0x1000); 567 reg[2] = htobe64(gicc_base); 568 reg[3] = htobe64(0x100); 569 break; 570 case 3: 571 /* GICv3 */ 572 compat = "arm,gic-v3"; 573 reg[0] = htobe64(gicd_base); 574 reg[1] = htobe64(0x10000); 575 reg[2] = htobe64(gicr_base); 576 reg[3] = htobe64(gicr_size); 577 break; 578 default: 579 return; 580 } 581 582 /* Update "interrupt-controller" node. */ 583 node = fdt_find_node("/interrupt-controller"); 584 fdt_node_set_string_property(node, "compatible", compat); 585 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 586 fdt_node_set_string_property(node, "status", "okay"); 587 } 588 589 void 590 efi_acpi_spcr(struct acpi_table_header *hdr) 591 { 592 struct acpi_spcr *spcr = (struct acpi_spcr *)hdr; 593 uint64_t reg[2], reg_shift, reg_io_width; 594 void *node; 595 596 /* Minimal revision required by Server Base Boot Requirements is 2. */ 597 if (spcr->hdr_revision < 2) 598 return; 599 600 /* No idea how to support anything else on ARM. */ 601 if (spcr->base_address.address_space_id != GAS_SYSTEM_MEMORY) 602 return; 603 604 reg[0] = htobe64(spcr->base_address.address); 605 606 switch (spcr->base_address.access_size) { 607 case GAS_ACCESS_BYTE: 608 reg_io_width = 1; 609 break; 610 case GAS_ACCESS_WORD: 611 reg_io_width = 2; 612 break; 613 case GAS_ACCESS_DWORD: 614 reg_io_width = 4; 615 break; 616 case GAS_ACCESS_QWORD: 617 reg_io_width = 8; 618 break; 619 default: 620 return; 621 } 622 reg_io_width = htobe32(reg_io_width); 623 624 reg_shift = 0; 625 if (spcr->base_address.register_bit_width > 8) 626 reg_shift = 1; 627 if (spcr->base_address.register_bit_width > 16) 628 reg_shift = 2; 629 if (spcr->base_address.register_bit_width > 32) 630 reg_shift = 3; 631 reg_shift = htobe32(reg_shift); 632 633 /* Update "serial" node. */ 634 node = fdt_find_node("/serial"); 635 switch (spcr->interface_type) { 636 case SPCR_16550: 637 case SPCR_16450: 638 fdt_node_set_string_property(node, "compatible", 639 "snps,dw-apb-uart"); 640 fdt_node_add_property(node, "reg-shift", 641 ®_shift, sizeof(reg_shift)); 642 fdt_node_add_property(node, "reg-io-width", 643 ®_io_width, sizeof(reg_io_width)); 644 reg[1] = htobe64(0x100); 645 break; 646 case SPCR_ARM_PL011: 647 case SPCR_ARM_SBSA: 648 fdt_node_set_string_property(node, "compatible", "arm,pl011"); 649 reg[1] = htobe64(0x1000); 650 break; 651 default: 652 return; 653 } 654 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 655 } 656 657 void * 658 efi_acpi(void) 659 { 660 extern u_char dt_blob_start[]; 661 void *fdt = dt_blob_start; 662 struct acpi_table_header *hdr; 663 struct acpi_rsdp *rsdp = NULL; 664 struct acpi_xsdt *xsdt; 665 uint64_t reg[2]; 666 int i, ntables; 667 size_t len; 668 void *node; 669 670 for (i = 0; i < ST->NumberOfTableEntries; i++) { 671 if (efi_guidcmp(&acpi_guid, 672 &ST->ConfigurationTable[i].VendorGuid) == 0) 673 rsdp = ST->ConfigurationTable[i].VendorTable; 674 } 675 676 if (rsdp == NULL) 677 return NULL; 678 679 if (memcmp(rsdp->rsdp_signature, RSDP_SIG, 8) != 0 || 680 rsdp->rsdp_revision < 2) 681 return NULL; 682 683 xsdt = (struct acpi_xsdt *)rsdp->rsdp_xsdt; 684 len = xsdt->hdr.length; 685 ntables = (len - sizeof(struct acpi_table_header)) / 686 sizeof(xsdt->table_offsets[0]); 687 if (ntables == 0) 688 return NULL; 689 690 if (!fdt_init(fdt)) 691 return NULL; 692 693 for (i = 0; i < ntables; i++) { 694 hdr = (struct acpi_table_header *)xsdt->table_offsets[i]; 695 printf("%c%c%c%c ", hdr->signature[0], hdr->signature[1], 696 hdr->signature[2], hdr->signature[3]); 697 if (memcmp(hdr->signature, FADT_SIG, 4) == 0) 698 efi_acpi_fadt(hdr); 699 if (memcmp(hdr->signature, GTDT_SIG, 4) == 0) 700 efi_acpi_gtdt(hdr); 701 if (memcmp(hdr->signature, MADT_SIG, 4) == 0) 702 efi_acpi_madt(hdr); 703 if (memcmp(hdr->signature, SPCR_SIG, 4) == 0) 704 efi_acpi_spcr(hdr); 705 } 706 printf("\n"); 707 708 reg[0] = htobe64((uint64_t)rsdp); 709 reg[1] = htobe64(rsdp->rsdp_length); 710 711 /* Update "acpi" node. */ 712 node = fdt_find_node("/acpi"); 713 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 714 715 fdt_finalize(); 716 717 return fdt; 718 } 719