1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// Coreboot interface support.
//
// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "acpi.h" // struct rsdp_descriptor
#include "config.h" // CONFIG_*
#include "malloc.h" // malloc_fseg
#include "output.h" // dprintf
#include "std/mptable.h" // MPTABLE_SIGNATURE
#include "std/pirtable.h" // struct pir_header
#include "std/smbios.h" // struct smbios_entry_point
#include "string.h" // memcpy
#include "util.h" // copy_table
static void
copy_pir(void *pos)
{
struct pir_header *p = pos;
if (p->signature != PIR_SIGNATURE)
return;
if (PirAddr)
return;
if (p->size < sizeof(*p))
return;
if (checksum(pos, p->size) != 0)
return;
void *newpos = malloc_fseg(p->size);
if (!newpos) {
warn_noalloc();
return;
}
dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
memcpy(newpos, pos, p->size);
PirAddr = newpos;
}
static void
copy_mptable(void *pos)
{
struct mptable_floating_s *p = pos;
if (p->signature != MPTABLE_SIGNATURE)
return;
if (!p->physaddr)
return;
if (checksum(pos, sizeof(*p)) != 0)
return;
u32 length = p->length * 16;
u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
if (!newpos) {
warn_noalloc();
return;
}
dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
memcpy(newpos, pos, length);
newpos->physaddr = (u32)newpos + length;
newpos->checksum -= checksum(newpos, sizeof(*newpos));
memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
}
static void
copy_acpi_rsdp(void *pos)
{
if (RsdpAddr)
return;
struct rsdp_descriptor *p = pos;
if (p->signature != RSDP_SIGNATURE)
return;
u32 length = 20;
if (checksum(pos, length) != 0)
return;
if (p->revision > 1) {
length = p->length;
if (checksum(pos, length) != 0)
return;
}
void *newpos = malloc_fseg(length);
if (!newpos) {
warn_noalloc();
return;
}
dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
memcpy(newpos, pos, length);
RsdpAddr = newpos;
}
void
copy_smbios(void *pos)
{
if (SMBiosAddr)
return;
struct smbios_entry_point *p = pos;
if (memcmp(p->anchor_string, "_SM_", 4))
return;
if (checksum(pos, 0x10) != 0)
return;
if (memcmp(p->intermediate_anchor_string, "_DMI_", 5))
return;
if (checksum(pos+0x10, p->length-0x10) != 0)
return;
struct smbios_entry_point *newpos = malloc_fseg(p->length);
if (!newpos) {
warn_noalloc();
return;
}
dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos);
memcpy(newpos, pos, p->length);
SMBiosAddr = newpos;
}
void
copy_table(void *pos)
{
copy_pir(pos);
copy_mptable(pos);
copy_acpi_rsdp(pos);
copy_smbios(pos);
}
|