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 */
add_apic_structure(s_acpi * acpi,uint8_t * q)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 
parse_madt(s_acpi * acpi)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