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