176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2009-2011 Erwan Velu - All Rights Reserved 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Permission is hereby granted, free of charge, to any person 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * obtaining a copy of this software and associated documentation 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * files (the "Software"), to deal in the Software without 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * restriction, including without limitation the rights to use, 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * copy, modify, merge, publish, distribute, sublicense, and/or 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * sell copies of the Software, and to permit persons to whom 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Software is furnished to do so, subject to the following 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * conditions: 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The above copyright notice and this permission notice shall 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * be included in all copies or substantial portions of the Software. 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OTHER DEALINGS IN THE SOFTWARE. 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/ 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h> 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <memory.h> 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <dprintf.h> 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdlib.h> 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "acpi/acpi.h" 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Parse the apic structures */ 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic uint8_t *add_apic_structure(s_acpi * acpi, uint8_t * q) 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t type = *q; 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q++; 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t length = *q; 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q++; 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_processor_local_apic *sla; 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_io_apic *sio; 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_interrupt_source_override *siso; 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_nmi *snmi; 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_local_apic_nmi *slan; 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_local_apic_address_override *slaao; 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_io_sapic *siosapic; 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_local_sapic *sls; 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_madt *madt = &acpi->madt; 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch (type) { 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case PROCESSOR_LOCAL_APIC: 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sla = &madt->processor_local_apic[madt->processor_local_apic_count]; 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sla->type = type; 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sla->length = length; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sla->acpi_id); 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sla->apic_id); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sla->flags); 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->processor_local_apic_count++; 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case IO_APIC: 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sio = &madt->io_apic[madt->io_apic_count]; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sio->type = type; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sio->length = length; 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sio->io_apic_id); 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sio->reserved); 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sio->io_apic_address); 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sio->global_system_interrupt_base); 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->io_apic_count++; 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case INTERRUPT_SOURCE_OVERRIDE: 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siso = 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &madt->interrupt_source_override[madt-> 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman interrupt_source_override_count]; 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siso->type = type; 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siso->length = length; 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siso->bus = *q; 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q++; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siso->source = *q; 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q++; 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siso->global_system_interrupt); 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siso->flags); 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->interrupt_source_override_count++; 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case NMI: 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman snmi = &madt->nmi[madt->nmi_count]; 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman snmi->type = type; 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman snmi->length = length; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&snmi->flags); 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&snmi->global_system_interrupt); 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->nmi_count++; 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LOCAL_APIC_NMI_STRUCTURE: 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slan = &madt->local_apic_nmi[madt->local_apic_nmi_count]; 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slan->type = type; 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slan->length = length; 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&slan->acpi_processor_id); 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&slan->flags); 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&slan->local_apic_lint); 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->local_apic_nmi_count++; 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE: 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slaao = 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &madt->local_apic_address_override[madt-> 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman local_apic_address_override_count]; 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slaao->type = type; 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman slaao->length = length; 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&slaao->reserved); 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&slaao->local_apic_address); 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->local_apic_address_override_count++; 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case IO_SAPIC: 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siosapic = &madt->io_sapic[madt->io_sapic_count]; 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siosapic->type = type; 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman siosapic->length = length; 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siosapic->io_apic_id); 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siosapic->reserved); 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siosapic->global_system_interrupt_base); 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&siosapic->io_sapic_address); 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->io_sapic_count++; 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case LOCAL_SAPIC: 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sls = &madt->local_sapic[madt->local_sapic_count]; 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sls->type = type; 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sls->length = length; 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sls->acpi_processor_id); 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sls->local_sapic_id); 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sls->local_sapic_eid); 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(sls->reserved); 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sls->flags); 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&sls->acpi_processor_uid_value); 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((sls->acpi_processor_uid_string = 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman malloc(length - ACPI_PROCESSOR_UID_STRING_OFFSET)) != NULL) { 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(sls->acpi_processor_uid_string, q, 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman length - ACPI_PROCESSOR_UID_STRING_OFFSET); 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q += length - ACPI_PROCESSOR_UID_STRING_OFFSET; 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman madt->local_sapic_count++; 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman printf("Unkown APIC structure type %u, size=%u \n", type, length); 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q += length - 2; 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return q; 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid parse_madt(s_acpi * acpi) 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Let's seach for FADT table */ 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t *q, *max_address; 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman s_madt *m = &acpi->madt; 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Fixing table name */ 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy(m->header.signature, APIC, sizeof(APIC)); 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Copying remaining structs */ 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q = (uint8_t *)m->address; 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q += ACPI_HEADER_SIZE; 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman max_address = (uint8_t *)m->address; 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman max_address += m->header.length; 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&m->local_apic_address); 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman cp_struct(&m->flags); 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman while (q < max_address) { 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman q = add_apic_structure(acpi, q); 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 173