acpi_table_header_t *mon_acpi_locate_table(char *sig) { acpi_table_rsdp_t *rsdp = NULL; void *table = NULL; /* Try 0x0 first for getting rsdp table */ rsdp = scan_for_rsdp(acpi_map_memory(0), 0x400); if (NULL == rsdp) { /* Try 0xE0000 */ MON_LOG(mask_anonymous, level_trace, "Try 0xE0000 for ACPI RSDP table\n"); rsdp = scan_for_rsdp(acpi_map_memory(0xE0000), 0x1FFFF); } if (NULL == rsdp) { MON_LOG(mask_anonymous, level_error, "Could not find the rsdp table\n"); return NULL; } MON_LOG(mask_anonymous, level_trace, "rsdp address %p\n", rsdp); /* Get the specified table from rsdp */ table = get_acpi_table_from_rsdp(rsdp, sig); return table; }
static const struct acpi_rsdp *find_rsdp(void) { uint32_t ebda; const struct acpi_rsdp *rsdp; ebda = (*(uint16_t *)0x40e) << 4; if (ebda >= 0x70000 && ebda < 0xa0000) { rsdp = scan_for_rsdp(ebda, ebda+1024); if (rsdp) return rsdp; } return scan_for_rsdp(0xe0000, 0x100000); }
/* This is where we search for SMP information in the following order * look for a floating MP pointer * found: * check for a default configuration * found: * setup config, return * check for a MP config table * found: * validate: * good: * parse the MP config table * good: * setup config, return * * find & validate ACPI RSDP (Root System Descriptor Pointer) * found: * find & validate RSDT (Root System Descriptor Table) * found: * find & validate MSDT * found: * parse the MADT table * good: * setup config, return */ void smp_find_cpus() { floating_pointer_struct_t *fp; rsdp_t *rp; rsdt_t *rt; uint8_t *tab_ptr, *tab_end; unsigned int *ptr; unsigned int uiptr; if(v->fail_safe & 3) { return; } memset(&AP, 0, sizeof AP); if(v->fail_safe & 8) { // Search for the Floating MP structure pointer fp = scan_for_floating_ptr_struct(0x0, 0x400); if (fp == NULL) { fp = scan_for_floating_ptr_struct(639*0x400, 0x400); } if (fp == NULL) { fp = scan_for_floating_ptr_struct(0xf0000, 0x10000); } if (fp == NULL) { // Search the BIOS ESDS area unsigned int address = *(unsigned short *)0x40E; address <<= 4; if (address) { fp = scan_for_floating_ptr_struct(address, 0x400); } } if (fp != NULL) { // We have a floating MP pointer // Is this a default configuration? if (fp->feature[0] > 0 && fp->feature[0] <=7) { // This is a default config so plug in the numbers num_cpus = 2; APIC = (volatile apic_register_t*)0xFEE00000; cpu_num_to_apic_id[0] = 0; cpu_num_to_apic_id[1] = 1; return; } // Do we have a pointer to a MP configuration table? if ( fp->phys_addr != 0) { if (read_mp_config_table(fp->phys_addr)) { // Found a good MP table, done return; } } } } /* No MP table so far, try to find an ACPI MADT table * We try to use the MP table first since there is no way to distinguish * real cores from hyper-threads in the MADT */ /* Search for the RSDP */ rp = scan_for_rsdp(0xE0000, 0x20000); if (rp == NULL) { /* Search the BIOS ESDS area */ unsigned int address = *(unsigned short *)0x40E; address <<= 4; if (address) { rp = scan_for_rsdp(address, 0x400); } } if (rp == NULL) { /* RSDP not found, give up */ return; } /* Found the RSDP, now get either the RSDT or XSDT */ if (rp->revision >= 2) { rt = (rsdt_t *)rp->xrsdt[0]; if (rt == 0) { return; } // Validate the XSDT if (*(unsigned int *)rt != XSDTSignature) { return; } if ( checksum((unsigned char*)rt, rt->length) != 0) { return; } } else { rt = (rsdt_t *)rp->rsdt; if (rt == 0) { return; } /* Validate the RSDT */ if (*(unsigned int *)rt != RSDTSignature) { return; } if ( checksum((unsigned char*)rt, rt->length) != 0) { return; } } /* Scan the RSDT or XSDT for a pointer to the MADT */ tab_ptr = ((uint8_t*)rt) + sizeof(rsdt_t); tab_end = ((uint8_t*)rt) + rt->length; while (tab_ptr < tab_end) { uiptr = *((unsigned int *)tab_ptr); ptr = (unsigned int *)uiptr; /* Check for the MADT signature */ if (ptr && *ptr == MADTSignature) { /* Found it, now parse it */ if (parse_madt((uintptr_t)ptr)) { return; } } tab_ptr += 4; } }