1 | /*␊ |
2 | * smp.c␊ |
3 | * Chameleon␊ |
4 | *␊ |
5 | * Created by cparm on 17/06/11.␊ |
6 | * Copyright 2011 __MyCompanyName__. All rights reserved.␊ |
7 | *␊ |
8 | */␊ |
9 | ␊ |
10 | #include "smp.h"␊ |
11 | #include "libsaio.h"␊ |
12 | ␊ |
13 | #define ACPI_RANGE_START (0x0E0000)␊ |
14 | #define ACPI_RANGE_END (0x0FFFFF)␊ |
15 | ␊ |
16 | static struct mp_t *␊ |
17 | bios_search_mp(char *base, int length);␊ |
18 | static struct mp_t* getAddressOfMPSTable();␊ |
19 | ␊ |
20 | static int lapic_dummy = 0;␊ |
21 | unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;␊ |
22 | ␊ |
23 | struct mp_t {␊ |
24 | ␉uint8_t sig[4];␊ |
25 | ␉uint32_t config_ptr;␊ |
26 | ␉uint8_t len;␊ |
27 | ␉uint8_t ver;␊ |
28 | ␉uint8_t checksum;␊ |
29 | ␉uint8_t f1;␊ |
30 | ␉uint8_t f2;␊ |
31 | ␉uint8_t fr[3];␊ |
32 | }__attribute__((packed)) mp_t;␊ |
33 | ␊ |
34 | static struct mp_t* getAddressOfMPSTable()␊ |
35 | {␊ |
36 | ␉struct mp_t *mp;␊ |
37 | uint16_t␉␉*addr;␊ |
38 | ␉␊ |
39 | /* EBDA is the 1 KB addressed by the 16 bit pointer at 0x40E. */␊ |
40 | addr = (uint16_t *)ptov(EBDA_SEG_ADDR);␊ |
41 | if ((mp = bios_search_mp((char *)(*addr << 4), EBDA_SEG_LEN)) != NULL)␊ |
42 | ␉␉return (mp);␊ |
43 | ␉␊ |
44 | ␉unsigned mem_lower = ((CMOS_READ_BYTE(CMOS_BASE_MEMORY+1) << 8)␊ |
45 | ␉␉␉␉␉␉ | CMOS_READ_BYTE(CMOS_BASE_MEMORY)) << 10;␊ |
46 | ␉␊ |
47 | ␉if ((mp = bios_search_mp((char *)mem_lower, EBDA_SEG_LEN)) != NULL)␊ |
48 | ␉␉return (mp);␊ |
49 | ␉␊ |
50 | if ((mp = bios_search_mp((char *)0x00F0000, ACPI_RANGE_END)) != NULL)␊ |
51 | ␉␉return (mp);␊ |
52 | ␉␊ |
53 | return (NULL);␊ |
54 | ␉␊ |
55 | }␊ |
56 | ␊ |
57 | static struct mp_t *␊ |
58 | bios_search_mp(char *base, int length)␊ |
59 | {␊ |
60 | ␉struct mp_t *mp;␊ |
61 | int␉␉␉ofs;␊ |
62 | ␉␊ |
63 | /* search on 16-byte boundaries */␊ |
64 | for (ofs = 0; ofs < length; ofs += 16) {␊ |
65 | ␉␉␊ |
66 | ␉␉mp = (struct mp_t*)ptov(base + ofs);␊ |
67 | ␉␉␊ |
68 | ␉␉/* compare signature, validate checksum */␊ |
69 | ␉␉if (!strncmp((char*)mp->sig, MP_SIGSTR, strlen(MP_SIGSTR))) {␊ |
70 | ␉␉␉uint8_t csum = checksum8(mp, sizeof(struct mp_t));␊ |
71 | ␉␉␉if(csum == 0) { ␊ |
72 | ␉␉␉␉return mp;␊ |
73 | ␉␉␉}␊ |
74 | ␉␉␉␊ |
75 | ␉␉}␉␉␉␉␊ |
76 | ␉}␉␊ |
77 | return NULL;␊ |
78 | }␊ |
79 | ␊ |
80 | void * getMPSTable()␊ |
81 | {␉␊ |
82 | ␉struct mp_t *mps_p = getAddressOfMPSTable() ;␊ |
83 | ␊ |
84 | if (mps_p)␊ |
85 | {␉␉␊ |
86 | if (mps_p->config_ptr) {␊ |
87 | ␉␉␉␊ |
88 | struct imps_cth *local_cth_ptr␊ |
89 | = (struct imps_cth *)ptov(mps_p->config_ptr);␊ |
90 | ␉␉␉␊ |
91 | imps_lapic_addr = local_cth_ptr->lapic_addr;␊ |
92 | ␉␉␉␊ |
93 | } else {␊ |
94 | imps_lapic_addr = LAPIC_ADDR_DEFAULT;␊ |
95 | }␉␉␊ |
96 | ␉}␊ |
97 | ␉␊ |
98 | ␉return (void *)mps_p;␊ |
99 | } |