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