1 /* $OpenBSD: efiacpi.c,v 1.8 2020/05/11 16:12:46 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 /* Skip disabled CPUs. */ 417 if ((gicc->flags & ACPI_PROC_ENABLE) == 0) 418 return; 419 420 /* 421 * MPIDR field was introduced in ACPI 5.1. Fall back on the 422 * ACPI Processor UID on ACPI 5.0. 423 */ 424 mpidr = (gicc->length >= 76) ? gicc->mpidr : gicc->acpi_proc_uid; 425 426 snprintf(name, sizeof(name), "cpu@%llx", mpidr); 427 reg = htobe64(mpidr); 428 429 /* Create "cpu" node. */ 430 node = fdt_find_node("/cpus"); 431 fdt_node_add_node(node, name, &child); 432 fdt_node_add_string_property(child, "device_type", "cpu"); 433 fdt_node_add_string_property(child, "compatible", "arm,armv8"); 434 fdt_node_add_property(child, "reg", ®, sizeof(reg)); 435 if (gicc->parking_protocol_version == 0 || psci) 436 fdt_node_add_string_property(child, "enable-method", "psci"); 437 438 /* Stash GIC information. */ 439 gicc_base = gicc->base_address; 440 } 441 442 void 443 efi_acpi_madt_gicd(struct acpi_madt_gicd *gicd) 444 { 445 /* Stash GIC information. */ 446 gic_version = gicd->version; 447 gicd_base = gicd->base_address; 448 } 449 450 void 451 efi_acpi_madt_gic_msi(struct acpi_madt_gic_msi *msi) 452 { 453 static uint32_t phandle = 2; 454 void *node, *child; 455 uint64_t reg[2]; 456 char name[32]; 457 458 snprintf(name, sizeof(name), "v2m@%llx", msi->base_address); 459 reg[0] = htobe64(msi->base_address); 460 reg[1] = htobe64(0x1000); 461 462 /* Create "v2m" node. */ 463 node = fdt_find_node("/interrupt-controller"); 464 fdt_node_add_node(node, name, &child); 465 fdt_node_add_string_property(child, "compatible", "arm,gic-v2m-frame"); 466 fdt_node_add_property(child, "msi-controller", NULL, 0); 467 fdt_node_add_property(child, "reg", reg, sizeof(reg)); 468 if (msi->flags & ACPI_MADT_GIC_MSI_SPI_SELECT) { 469 uint32_t spi_base = msi->spi_base; 470 uint32_t spi_count = msi->spi_count; 471 472 fdt_node_add_property(child, "arm,msi-base-spi", 473 &spi_base, sizeof(spi_base)); 474 fdt_node_add_property(child, "arm,msi-num-spis", 475 &spi_count, sizeof(spi_count)); 476 } 477 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle)); 478 phandle++; 479 } 480 481 void 482 efi_acpi_madt_gicr(struct acpi_madt_gicr *gicr) 483 { 484 /* Stash GIC information. */ 485 gicr_base = gicr->discovery_base_address; 486 gicr_size = gicr->discovery_length; 487 } 488 489 void 490 efi_acpi_madt_gic_its(struct acpi_madt_gic_its *its) 491 { 492 static uint32_t phandle = 2; 493 void *node, *child; 494 uint64_t reg[2]; 495 char name[32]; 496 497 snprintf(name, sizeof(name), "gic-its@%llx", its->base_address); 498 reg[0] = htobe64(its->base_address); 499 reg[1] = htobe64(0x20000); 500 501 /* Create "gic-its" node. */ 502 node = fdt_find_node("/interrupt-controller"); 503 fdt_node_add_node(node, name, &child); 504 fdt_node_add_string_property(child, "compatible", "arm,gic-v3-its"); 505 fdt_node_add_property(child, "msi-controller", NULL, 0); 506 fdt_node_add_property(child, "reg", reg, sizeof(reg)); 507 fdt_node_add_property(child, "phandle", &phandle, sizeof(phandle)); 508 phandle++; 509 } 510 511 void 512 efi_acpi_madt(struct acpi_table_header *hdr) 513 { 514 struct acpi_madt *madt = (struct acpi_madt *)hdr; 515 char *compat; 516 uint64_t reg[4]; 517 char *addr; 518 void *node; 519 520 /* GIC support was introduced in ACPI 5.0. */ 521 if (madt->hdr_revision < 3) 522 return; 523 524 addr = (char *)(madt + 1); 525 while (addr < (char *)madt + madt->hdr.length) { 526 union acpi_madt_entry *entry = (union acpi_madt_entry *)addr; 527 uint8_t length = entry->madt_gicc.length; 528 529 if (length < 2) 530 return; 531 532 if (addr + length > (char *)madt + madt->hdr_length) 533 return; 534 535 switch (entry->madt_gicc.apic_type) { 536 case ACPI_MADT_GICC: 537 efi_acpi_madt_gicc(&entry->madt_gicc); 538 break; 539 case ACPI_MADT_GICD: 540 efi_acpi_madt_gicd(&entry->madt_gicd); 541 break; 542 case ACPI_MADT_GIC_MSI: 543 efi_acpi_madt_gic_msi(&entry->madt_gic_msi); 544 break; 545 case ACPI_MADT_GICR: 546 efi_acpi_madt_gicr(&entry->madt_gicr); 547 break; 548 case ACPI_MADT_GIC_ITS: 549 efi_acpi_madt_gic_its(&entry->madt_gic_its); 550 break; 551 } 552 553 addr += length; 554 } 555 556 /* 557 * Now that we've collected all the necessary information, fix 558 * up the "interrupt-controller" node. 559 */ 560 561 switch (gic_version) { 562 case 0: 563 /* ACPI 5.0 doesn't provide a version; assume GICv2 */ 564 case 2: 565 /* GICv2 */ 566 compat = "arm,gic-400"; 567 reg[0] = htobe64(gicd_base); 568 reg[1] = htobe64(0x1000); 569 reg[2] = htobe64(gicc_base); 570 reg[3] = htobe64(0x100); 571 break; 572 case 3: 573 /* GICv3 */ 574 compat = "arm,gic-v3"; 575 reg[0] = htobe64(gicd_base); 576 reg[1] = htobe64(0x10000); 577 reg[2] = htobe64(gicr_base); 578 reg[3] = htobe64(gicr_size); 579 break; 580 default: 581 return; 582 } 583 584 /* Update "interrupt-controller" node. */ 585 node = fdt_find_node("/interrupt-controller"); 586 fdt_node_set_string_property(node, "compatible", compat); 587 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 588 fdt_node_set_string_property(node, "status", "okay"); 589 } 590 591 static int serial = 0; 592 593 void 594 efi_acpi_spcr(struct acpi_table_header *hdr) 595 { 596 struct acpi_spcr *spcr = (struct acpi_spcr *)hdr; 597 uint64_t reg[2], reg_shift, reg_io_width; 598 void *node; 599 600 /* Minimal revision required by Server Base Boot Requirements is 2. */ 601 if (spcr->hdr_revision < 2) 602 return; 603 604 /* No idea how to support anything else on ARM. */ 605 if (spcr->base_address.address_space_id != GAS_SYSTEM_MEMORY) 606 return; 607 608 reg[0] = htobe64(spcr->base_address.address); 609 610 switch (spcr->base_address.access_size) { 611 case GAS_ACCESS_BYTE: 612 reg_io_width = 1; 613 break; 614 case GAS_ACCESS_WORD: 615 reg_io_width = 2; 616 break; 617 case GAS_ACCESS_DWORD: 618 reg_io_width = 4; 619 break; 620 case GAS_ACCESS_QWORD: 621 reg_io_width = 8; 622 break; 623 default: 624 return; 625 } 626 reg_io_width = htobe32(reg_io_width); 627 628 reg_shift = 0; 629 if (spcr->base_address.register_bit_width > 8) 630 reg_shift = 1; 631 if (spcr->base_address.register_bit_width > 16) 632 reg_shift = 2; 633 if (spcr->base_address.register_bit_width > 32) 634 reg_shift = 3; 635 reg_shift = htobe32(reg_shift); 636 637 /* Update "serial" node. */ 638 node = fdt_find_node("/serial"); 639 switch (spcr->interface_type) { 640 case SPCR_16550: 641 case SPCR_16450: 642 fdt_node_set_string_property(node, "compatible", 643 "snps,dw-apb-uart"); 644 fdt_node_add_property(node, "reg-shift", 645 ®_shift, sizeof(reg_shift)); 646 fdt_node_add_property(node, "reg-io-width", 647 ®_io_width, sizeof(reg_io_width)); 648 reg[1] = htobe64(0x100); 649 break; 650 case SPCR_ARM_PL011: 651 case SPCR_ARM_SBSA: 652 fdt_node_set_string_property(node, "compatible", "arm,pl011"); 653 reg[1] = htobe64(0x1000); 654 break; 655 default: 656 return; 657 } 658 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 659 serial = 1; 660 } 661 662 void * 663 efi_acpi(void) 664 { 665 extern uint64_t dma_constraint[2]; 666 extern u_char dt_blob_start[]; 667 void *fdt = dt_blob_start; 668 struct acpi_table_header *hdr; 669 struct acpi_rsdp *rsdp = NULL; 670 struct acpi_xsdt *xsdt; 671 uint64_t reg[2]; 672 int i, ntables; 673 size_t len; 674 void *node; 675 676 for (i = 0; i < ST->NumberOfTableEntries; i++) { 677 if (efi_guidcmp(&acpi_guid, 678 &ST->ConfigurationTable[i].VendorGuid) == 0) 679 rsdp = ST->ConfigurationTable[i].VendorTable; 680 } 681 682 if (rsdp == NULL) 683 return NULL; 684 685 if (memcmp(rsdp->rsdp_signature, RSDP_SIG, 8) != 0 || 686 rsdp->rsdp_revision < 2) 687 return NULL; 688 689 xsdt = (struct acpi_xsdt *)rsdp->rsdp_xsdt; 690 len = xsdt->hdr.length; 691 ntables = (len - sizeof(struct acpi_table_header)) / 692 sizeof(xsdt->table_offsets[0]); 693 if (ntables == 0) 694 return NULL; 695 696 if (!fdt_init(fdt)) 697 return NULL; 698 699 for (i = 0; i < ntables; i++) { 700 hdr = (struct acpi_table_header *)xsdt->table_offsets[i]; 701 printf("%c%c%c%c ", hdr->signature[0], hdr->signature[1], 702 hdr->signature[2], hdr->signature[3]); 703 if (memcmp(hdr->signature, FADT_SIG, 4) == 0) 704 efi_acpi_fadt(hdr); 705 if (memcmp(hdr->signature, GTDT_SIG, 4) == 0) 706 efi_acpi_gtdt(hdr); 707 if (memcmp(hdr->signature, MADT_SIG, 4) == 0) 708 efi_acpi_madt(hdr); 709 if (memcmp(hdr->signature, SPCR_SIG, 4) == 0) 710 efi_acpi_spcr(hdr); 711 } 712 printf("\n"); 713 714 reg[0] = htobe64((uint64_t)rsdp); 715 reg[1] = htobe64(rsdp->rsdp_length); 716 717 /* Update "acpi" node. */ 718 node = fdt_find_node("/acpi"); 719 fdt_node_set_property(node, "reg", reg, sizeof(reg)); 720 721 /* Use framebuffer if SPCR is absent or unusable. */ 722 if (!serial) 723 cnset(ttydev("fb0")); 724 725 /* Raspberry Pi 4 is "special". */ 726 if (memcmp(xsdt->hdr_oemid, "RPIFDN", 6) == 0 && 727 memcmp(xsdt->hdr_oemtableid, "RPI4", 4) == 0) 728 dma_constraint[1] = htobe64(0x3bffffff); 729 730 fdt_finalize(); 731 732 return fdt; 733 } 734