blob: 81cc79b2f87b5037b76c14c6934a309f0195e3ae [file] [log] [blame]
Ian Campbell1442c312011-06-01 11:00:28 +01001// Coreboot interface support.
2//
3// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
4//
5// This file may be distributed under the terms of the GNU LGPLv3 license.
6
7#include "config.h" // CONFIG_*
8#include "util.h" // dprintf
9#include "pci.h" // struct pir_header
10#include "acpi.h" // struct rsdp_descriptor
11#include "mptable.h" // MPTABLE_SIGNATURE
Ian Campbell74c78782011-06-01 11:00:29 +010012#include "smbios.h" // struct smbios_entry_point
Ian Campbell1442c312011-06-01 11:00:28 +010013
Kevin O'Connor4d053eb2012-06-09 13:08:02 -040014static void
Ian Campbell1442c312011-06-01 11:00:28 +010015copy_pir(void *pos)
16{
17 struct pir_header *p = pos;
18 if (p->signature != PIR_SIGNATURE)
19 return;
Kevin O'Connorbfa02cd2012-06-09 13:36:45 -040020 if (PirAddr)
Ian Campbell1442c312011-06-01 11:00:28 +010021 return;
22 if (p->size < sizeof(*p))
23 return;
24 if (checksum(pos, p->size) != 0)
25 return;
26 void *newpos = malloc_fseg(p->size);
27 if (!newpos) {
28 warn_noalloc();
29 return;
30 }
31 dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
32 memcpy(newpos, pos, p->size);
Kevin O'Connorbfa02cd2012-06-09 13:36:45 -040033 PirAddr = newpos;
Ian Campbell1442c312011-06-01 11:00:28 +010034}
35
Kevin O'Connor4d053eb2012-06-09 13:08:02 -040036static void
Ian Campbell1442c312011-06-01 11:00:28 +010037copy_mptable(void *pos)
38{
39 struct mptable_floating_s *p = pos;
40 if (p->signature != MPTABLE_SIGNATURE)
41 return;
42 if (!p->physaddr)
43 return;
44 if (checksum(pos, sizeof(*p)) != 0)
45 return;
46 u32 length = p->length * 16;
47 u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
48 struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
49 if (!newpos) {
50 warn_noalloc();
51 return;
52 }
53 dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
54 memcpy(newpos, pos, length);
55 newpos->physaddr = (u32)newpos + length;
56 newpos->checksum -= checksum(newpos, sizeof(*newpos));
57 memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
58}
59
Kevin O'Connor4d053eb2012-06-09 13:08:02 -040060static void
Ian Campbell1442c312011-06-01 11:00:28 +010061copy_acpi_rsdp(void *pos)
62{
63 if (RsdpAddr)
64 return;
65 struct rsdp_descriptor *p = pos;
66 if (p->signature != RSDP_SIGNATURE)
67 return;
68 u32 length = 20;
69 if (checksum(pos, length) != 0)
70 return;
71 if (p->revision > 1) {
72 length = p->length;
73 if (checksum(pos, length) != 0)
74 return;
75 }
76 void *newpos = malloc_fseg(length);
77 if (!newpos) {
78 warn_noalloc();
79 return;
80 }
81 dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
82 memcpy(newpos, pos, length);
83 RsdpAddr = newpos;
84}
Ian Campbell74c78782011-06-01 11:00:29 +010085
Kevin O'Connor4d053eb2012-06-09 13:08:02 -040086static void
Ian Campbell74c78782011-06-01 11:00:29 +010087copy_smbios(void *pos)
88{
Kevin O'Connor83012de2011-08-28 12:42:15 -040089 if (SMBiosAddr)
90 return;
Ian Campbell74c78782011-06-01 11:00:29 +010091 struct smbios_entry_point *p = pos;
92 if (memcmp(p->anchor_string, "_SM_", 4))
93 return;
94 if (checksum(pos, 0x10) != 0)
95 return;
96 if (memcmp(p->intermediate_anchor_string, "_DMI_", 5))
97 return;
98 if (checksum(pos+0x10, p->length-0x10) != 0)
99 return;
Ian Campbellee2bc462011-06-14 15:22:09 +0100100 struct smbios_entry_point *newpos = malloc_fseg(p->length);
Ian Campbell74c78782011-06-01 11:00:29 +0100101 if (!newpos) {
102 warn_noalloc();
103 return;
104 }
105 dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos);
106 memcpy(newpos, pos, p->length);
Kevin O'Connor83012de2011-08-28 12:42:15 -0400107 SMBiosAddr = newpos;
Ian Campbell74c78782011-06-01 11:00:29 +0100108}
Kevin O'Connor4d053eb2012-06-09 13:08:02 -0400109
110void
111copy_table(void *pos)
112{
113 copy_pir(pos);
114 copy_mptable(pos);
115 copy_acpi_rsdp(pos);
116 copy_smbios(pos);
117}