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