Home | History | Annotate | Download | only in acpi
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2009-2011 Erwan Velu - All Rights Reserved
      4  *
      5  *   Permission is hereby granted, free of charge, to any person
      6  *   obtaining a copy of this software and associated documentation
      7  *   files (the "Software"), to deal in the Software without
      8  *   restriction, including without limitation the rights to use,
      9  *   copy, modify, merge, publish, distribute, sublicense, and/or
     10  *   sell copies of the Software, and to permit persons to whom
     11  *   the Software is furnished to do so, subject to the following
     12  *   conditions:
     13  *
     14  *   The above copyright notice and this permission notice shall
     15  *   be included in all copies or substantial portions of the Software.
     16  *
     17  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     19  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     21  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     22  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  *   OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * -----------------------------------------------------------------------
     27 */
     28 
     29 #include <stdio.h>
     30 #include <string.h>
     31 #include <memory.h>
     32 #include <dprintf.h>
     33 #include <stdlib.h>
     34 #include "acpi/acpi.h"
     35 
     36 /* Parse the apic structures */
     37 static uint8_t *add_apic_structure(s_acpi * acpi, uint8_t * q)
     38 {
     39     uint8_t type = *q;
     40     q++;
     41     uint8_t length = *q;
     42     q++;
     43     s_processor_local_apic *sla;
     44     s_io_apic *sio;
     45     s_interrupt_source_override *siso;
     46     s_nmi *snmi;
     47     s_local_apic_nmi *slan;
     48     s_local_apic_address_override *slaao;
     49     s_io_sapic *siosapic;
     50     s_local_sapic *sls;
     51     s_madt *madt = &acpi->madt;
     52 
     53     switch (type) {
     54     case PROCESSOR_LOCAL_APIC:
     55 	sla = &madt->processor_local_apic[madt->processor_local_apic_count];
     56 	sla->type = type;
     57 	sla->length = length;
     58 	cp_struct(&sla->acpi_id);
     59 	cp_struct(&sla->apic_id);
     60 	cp_struct(&sla->flags);
     61 	madt->processor_local_apic_count++;
     62 	break;
     63     case IO_APIC:
     64 	sio = &madt->io_apic[madt->io_apic_count];
     65 	sio->type = type;
     66 	sio->length = length;
     67 	cp_struct(&sio->io_apic_id);
     68 	cp_struct(&sio->reserved);
     69 	cp_struct(&sio->io_apic_address);
     70 	cp_struct(&sio->global_system_interrupt_base);
     71 	madt->io_apic_count++;
     72 	break;
     73     case INTERRUPT_SOURCE_OVERRIDE:
     74 	siso =
     75 	    &madt->interrupt_source_override[madt->
     76 					     interrupt_source_override_count];
     77 	siso->type = type;
     78 	siso->length = length;
     79 	siso->bus = *q;
     80 	q++;
     81 	siso->source = *q;
     82 	q++;
     83 	cp_struct(&siso->global_system_interrupt);
     84 	cp_struct(&siso->flags);
     85 	madt->interrupt_source_override_count++;
     86 	break;
     87     case NMI:
     88 	snmi = &madt->nmi[madt->nmi_count];
     89 	snmi->type = type;
     90 	snmi->length = length;
     91 	cp_struct(&snmi->flags);
     92 	cp_struct(&snmi->global_system_interrupt);
     93 	madt->nmi_count++;
     94 	break;
     95     case LOCAL_APIC_NMI_STRUCTURE:
     96 	slan = &madt->local_apic_nmi[madt->local_apic_nmi_count];
     97 	slan->type = type;
     98 	slan->length = length;
     99 	cp_struct(&slan->acpi_processor_id);
    100 	cp_struct(&slan->flags);
    101 	cp_struct(&slan->local_apic_lint);
    102 	madt->local_apic_nmi_count++;
    103 	break;
    104     case LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE:
    105 	slaao =
    106 	    &madt->local_apic_address_override[madt->
    107 					       local_apic_address_override_count];
    108 	slaao->type = type;
    109 	slaao->length = length;
    110 	cp_struct(&slaao->reserved);
    111 	cp_struct(&slaao->local_apic_address);
    112 	madt->local_apic_address_override_count++;
    113 	break;
    114     case IO_SAPIC:
    115 	siosapic = &madt->io_sapic[madt->io_sapic_count];
    116 	siosapic->type = type;
    117 	siosapic->length = length;
    118 	cp_struct(&siosapic->io_apic_id);
    119 	cp_struct(&siosapic->reserved);
    120 	cp_struct(&siosapic->global_system_interrupt_base);
    121 	cp_struct(&siosapic->io_sapic_address);
    122 	madt->io_sapic_count++;
    123 	break;
    124     case LOCAL_SAPIC:
    125 	sls = &madt->local_sapic[madt->local_sapic_count];
    126 	sls->type = type;
    127 	sls->length = length;
    128 	cp_struct(&sls->acpi_processor_id);
    129 	cp_struct(&sls->local_sapic_id);
    130 	cp_struct(&sls->local_sapic_eid);
    131 	cp_struct(sls->reserved);
    132 	cp_struct(&sls->flags);
    133 	cp_struct(&sls->acpi_processor_uid_value);
    134 	if ((sls->acpi_processor_uid_string =
    135 	     malloc(length - ACPI_PROCESSOR_UID_STRING_OFFSET)) != NULL) {
    136 	    memcpy(sls->acpi_processor_uid_string, q,
    137 		   length - ACPI_PROCESSOR_UID_STRING_OFFSET);
    138 	    q += length - ACPI_PROCESSOR_UID_STRING_OFFSET;
    139 	}
    140 	madt->local_sapic_count++;
    141 	break;
    142     default:
    143 	printf("Unkown APIC structure type %u, size=%u \n", type, length);
    144 	q += length - 2;
    145 	break;
    146     }
    147     return q;
    148 }
    149 
    150 void parse_madt(s_acpi * acpi)
    151 {
    152     /* Let's seach for FADT table */
    153     uint8_t *q, *max_address;
    154     s_madt *m = &acpi->madt;
    155 
    156     /* Fixing table name */
    157     memcpy(m->header.signature, APIC, sizeof(APIC));
    158 
    159     /* Copying remaining structs */
    160     q = (uint8_t *)m->address;
    161     q += ACPI_HEADER_SIZE;
    162 
    163     max_address = (uint8_t *)m->address;
    164     max_address += m->header.length;
    165 
    166     cp_struct(&m->local_apic_address);
    167     cp_struct(&m->flags);
    168 
    169     while (q <  max_address) {
    170 	q = add_apic_structure(acpi, q);
    171     }
    172 }
    173