2009-05-02 Vladimir Serbinenko <phcoder@gmail.com>
ACPI spoofing * commands/acpi.c: new file * commands/i386/pc/acpi.c: likewise * commands/efi/acpi.c: likewise * include/grub/acpi.h: likewise * conf/i386-pc.rmk (pkglib_MODULES): added acpi.mod (acpi_mod_SOURCES): new variable (acpi_mod_CFLAGS): likewise (acpi_mod_LDFLAGS): likewise * conf/i386-efi.rmk: likewise * conf/x86_64-efi.rmk: likewise
This commit is contained in:
parent
28a856658d
commit
f8efe3ad2d
8 changed files with 1024 additions and 3 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2009-05-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
ACPI spoofing
|
||||
|
||||
* commands/acpi.c: new file
|
||||
* commands/i386/pc/acpi.c: likewise
|
||||
* commands/efi/acpi.c: likewise
|
||||
* include/grub/acpi.h: likewise
|
||||
* conf/i386-pc.rmk (pkglib_MODULES): added acpi.mod
|
||||
(acpi_mod_SOURCES): new variable
|
||||
(acpi_mod_CFLAGS): likewise
|
||||
(acpi_mod_LDFLAGS): likewise
|
||||
* conf/i386-efi.rmk: likewise
|
||||
* conf/x86_64-efi.rmk: likewise
|
||||
|
||||
2009-05-02 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Missing part from mmap patch
|
||||
|
|
774
commands/acpi.c
Normal file
774
commands/acpi.c
Normal file
|
@ -0,0 +1,774 @@
|
|||
/* acpi.c - modify acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/gzio.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/machine/machine.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/memory.h>
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"exclude", 'x', 0,
|
||||
"Don't load host tables specified by comma-separated list",
|
||||
0, ARG_TYPE_STRING},
|
||||
{"load-only", 'n', 0,
|
||||
"Load only tables specified by comma-separated list", 0, ARG_TYPE_STRING},
|
||||
{"v1", '1', 0, "Expose v1 tables", 0, ARG_TYPE_NONE},
|
||||
{"v2", '2', 0, "Expose v2 and v3 tables", 0, ARG_TYPE_NONE},
|
||||
{"oemid", 'o', 0, "Set OEMID of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},
|
||||
{"oemtable", 't', 0,
|
||||
"Set OEMTABLE ID of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},
|
||||
{"oemtablerev", 'r', 0,
|
||||
"Set OEMTABLE revision of RSDP, XSDT and RSDT", 0, ARG_TYPE_INT},
|
||||
{"oemtablecreator", 'c', 0,
|
||||
"Set creator field of RSDP, XSDT and RSDT", 0, ARG_TYPE_STRING},
|
||||
{"oemtablecreatorrev", 'd', 0,
|
||||
"Set creator revision of RSDP, XSDT and RSDT", 0, ARG_TYPE_INT},
|
||||
{"no-ebda", 'e', 0, "Don't update EBDA. May fix failures or hangs on some"
|
||||
" BIOSes but makes it uneffective with OS not recieving RSDP fro GRUB",
|
||||
0, ARG_TYPE_NONE},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
|
||||
grub_uint8_t
|
||||
grub_byte_checksum (void *base, grub_size_t size)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
grub_uint8_t ret = 0;
|
||||
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
|
||||
ptr++)
|
||||
ret += *ptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
|
||||
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
|
||||
static int rev1, rev2;
|
||||
static grub_dl_t my_mod;
|
||||
/* OEMID of RSDP, RSDT and XSDT. */
|
||||
static char root_oemid[6];
|
||||
/* OEMTABLE of the same tables. */
|
||||
static char root_oemtable[8];
|
||||
/* OEMREVISION of the same tables. */
|
||||
static grub_uint32_t root_oemrev;
|
||||
/* CreatorID of the same tables. */
|
||||
static char root_creator_id[4];
|
||||
/* CreatorRevision of the same tables. */
|
||||
static grub_uint32_t root_creator_rev;
|
||||
static struct grub_acpi_rsdp_v10 *rsdpv1_new = 0;
|
||||
static struct grub_acpi_rsdp_v20 *rsdpv2_new = 0;
|
||||
static char *playground = 0, *playground_ptr = 0;
|
||||
static int playground_size = 0;
|
||||
|
||||
/* Linked list of ACPI tables. */
|
||||
struct efiemu_acpi_table
|
||||
{
|
||||
void *addr;
|
||||
grub_size_t size;
|
||||
struct efiemu_acpi_table *next;
|
||||
};
|
||||
static struct efiemu_acpi_table *acpi_tables = 0;
|
||||
|
||||
/* DSDT isn't in RSDT. So treat it specially. */
|
||||
static void *table_dsdt = 0;
|
||||
/* Pointer to recreated RSDT. */
|
||||
static void *rsdt_addr = 0;
|
||||
|
||||
/* Allocation handles for different tables. */
|
||||
static grub_size_t dsdt_size = 0;
|
||||
|
||||
/* Address of original FACS. */
|
||||
static grub_uint32_t facs_addr = 0;
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
if (rsdpv2_new)
|
||||
return rsdpv2_new;
|
||||
if (rsdpv1_new)
|
||||
return 0;
|
||||
return grub_machine_acpi_get_rsdpv2 ();
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
if (rsdpv1_new)
|
||||
return rsdpv1_new;
|
||||
if (rsdpv2_new)
|
||||
return 0;
|
||||
return grub_machine_acpi_get_rsdpv1 ();
|
||||
}
|
||||
|
||||
static inline int
|
||||
iszero (grub_uint8_t *reg, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
if (reg[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_acpi_create_ebda (void)
|
||||
{
|
||||
int ebda_kb_len;
|
||||
int ebda_len;
|
||||
int mmapregion = 0;
|
||||
grub_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0;
|
||||
grub_uint64_t highestlow = 0;
|
||||
grub_uint8_t *targetebda, *target;
|
||||
struct grub_acpi_rsdp_v10 *v1;
|
||||
struct grub_acpi_rsdp_v20 *v2;
|
||||
auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t,
|
||||
grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size,
|
||||
grub_uint32_t type)
|
||||
{
|
||||
grub_uint64_t end = start + size;
|
||||
if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
if (end > 0x100000)
|
||||
end = 0x100000;
|
||||
if (end > start + ebda_len
|
||||
&& highestlow < ((end - ebda_len) & (~0xf)) )
|
||||
highestlow = (end - ebda_len) & (~0xf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4);
|
||||
ebda_kb_len = *(grub_uint16_t *) ebda;
|
||||
if (! ebda || ebda_kb_len > 16)
|
||||
ebda_kb_len = 0;
|
||||
ebda_len = (ebda_kb_len + 1) << 10;
|
||||
|
||||
/* FIXME: use low-memory mm allocation once it's available. */
|
||||
grub_mmap_iterate (find_hook);
|
||||
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow);
|
||||
grub_dprintf ("acpi", "creating ebda @%llx\n",
|
||||
(unsigned long long) highestlow);
|
||||
if (! highestlow)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't find space for the new EBDA");
|
||||
|
||||
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
|
||||
GRUB_MACHINE_MEMORY_RESERVED);
|
||||
if (! mmapregion)
|
||||
return grub_errno;
|
||||
|
||||
/* XXX: EBDA is unstandartised, so this implementation is heuristical. */
|
||||
if (ebda_kb_len)
|
||||
grub_memcpy (targetebda, ebda, 0x400);
|
||||
else
|
||||
grub_memset (targetebda, 0, 0x400);
|
||||
*((grub_uint16_t *) targetebda) = ebda_kb_len + 1;
|
||||
target = targetebda;
|
||||
|
||||
v1 = grub_acpi_get_rsdpv1 ();
|
||||
v2 = grub_acpi_get_rsdpv2 ();
|
||||
if (v2 && v2->length > 40)
|
||||
v2 = 0;
|
||||
|
||||
/* First try to replace already existing rsdp. */
|
||||
if (v2)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
|
||||
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) target)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) target)->length <= v2->length)
|
||||
{
|
||||
grub_memcpy (target, v2, v2->length);
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
|
||||
for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0)
|
||||
{
|
||||
grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
target = targetebda + 0x100;
|
||||
|
||||
/* Try contiguous zeros. */
|
||||
if (v2)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
|
||||
for (; target < targetebda + 0x400 - v2->length; target += 0x10)
|
||||
if (iszero (target, v2->length))
|
||||
{
|
||||
grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
|
||||
grub_memcpy (target, v2, v2->length);
|
||||
v2inebda = target;
|
||||
target += v2->length;
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v2 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1)
|
||||
{
|
||||
grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
|
||||
for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (iszero (target, sizeof (struct grub_acpi_rsdp_v10)))
|
||||
{
|
||||
grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
|
||||
grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
|
||||
v1inebda = target;
|
||||
target += sizeof (struct grub_acpi_rsdp_v10);
|
||||
target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
|
||||
v1 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (v1 || v2)
|
||||
{
|
||||
grub_mmap_unregister (mmapregion);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Couldn't find suitable spot in EBDA");
|
||||
}
|
||||
|
||||
/* Remove any other RSDT. */
|
||||
for (target = targetebda;
|
||||
target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
|
||||
target += 0x10)
|
||||
if (grub_memcmp (target, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (target,
|
||||
sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& target != v1inebda && target != v2inebda)
|
||||
*target = 0;
|
||||
|
||||
grub_dprintf ("acpi", "Switching EBDA\n");
|
||||
(*((grub_uint16_t *) 0x40e)) = ((long)targetebda) >> 4;
|
||||
grub_dprintf ("acpi", "EBDA switched\n");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Create tables common to ACPIv1 and ACPIv2+ */
|
||||
static void
|
||||
setup_common_tables (void)
|
||||
{
|
||||
struct efiemu_acpi_table *cur;
|
||||
struct grub_acpi_table_header *rsdt;
|
||||
grub_uint32_t *rsdt_entry;
|
||||
int numoftables;
|
||||
|
||||
/* Treat DSDT. */
|
||||
grub_memcpy (playground_ptr, table_dsdt, dsdt_size);
|
||||
grub_free (table_dsdt);
|
||||
table_dsdt = playground_ptr;
|
||||
playground_ptr += dsdt_size;
|
||||
|
||||
/* Treat other tables. */
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
{
|
||||
struct grub_acpi_fadt *fadt;
|
||||
|
||||
grub_memcpy (playground_ptr, cur->addr, cur->size);
|
||||
grub_free (cur->addr);
|
||||
cur->addr = playground_ptr;
|
||||
playground_ptr += cur->size;
|
||||
|
||||
/* If it's FADT correct DSDT and FACS addresses. */
|
||||
fadt = (struct grub_acpi_fadt *) cur->addr;
|
||||
if (grub_memcmp (fadt->hdr.signature, "FACP", 4) == 0)
|
||||
{
|
||||
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
|
||||
fadt->facs_addr = facs_addr;
|
||||
|
||||
/* Does a revision 2 exist at all? */
|
||||
if (fadt->hdr.revision >= 3)
|
||||
{
|
||||
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt);
|
||||
fadt->facs_xaddr = facs_addr;
|
||||
}
|
||||
|
||||
/* Recompute checksum. */
|
||||
fadt->hdr.checksum = 0;
|
||||
fadt->hdr.checksum = 1 + ~grub_byte_checksum (fadt, fadt->hdr.length);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill RSDT entries. */
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
|
||||
rsdt_entry = (grub_uint32_t *)(rsdt + 1);
|
||||
|
||||
/* Fill RSDT header. */
|
||||
grub_memcpy (&(rsdt->signature), "RSDT", 4);
|
||||
rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
rsdt->revision = 1;
|
||||
grub_memcpy (&(rsdt->oemid), root_oemid, 6);
|
||||
grub_memcpy (&(rsdt->oemtable), root_oemtable, 4);
|
||||
rsdt->oemrev = root_oemrev;
|
||||
grub_memcpy (&(rsdt->creator_id), root_creator_id, 6);
|
||||
rsdt->creator_rev = root_creator_rev;
|
||||
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
|
||||
|
||||
/* Recompute checksum. */
|
||||
rsdt->checksum = 0;
|
||||
rsdt->checksum = 1 + ~grub_byte_checksum (rsdt, rsdt->length);
|
||||
}
|
||||
|
||||
/* Regenerate ACPIv1 RSDP */
|
||||
static void
|
||||
setv1table (void)
|
||||
{
|
||||
/* Create RSDP. */
|
||||
rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_rsdp_v10);
|
||||
grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", 8);
|
||||
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
|
||||
rsdpv1_new->revision = 0;
|
||||
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv1_new->checksum = 0;
|
||||
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
|
||||
sizeof (*rsdpv1_new));
|
||||
grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
|
||||
}
|
||||
|
||||
static void
|
||||
setv2table (void)
|
||||
{
|
||||
struct grub_acpi_table_header *xsdt;
|
||||
struct efiemu_acpi_table *cur;
|
||||
grub_uint64_t *xsdt_entry;
|
||||
int numoftables;
|
||||
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
/* Create XSDT. */
|
||||
xsdt = (struct grub_acpi_table_header *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
|
||||
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
|
||||
grub_memcpy (&(xsdt->signature), "XSDT", 4);
|
||||
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
xsdt->revision = 1;
|
||||
grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid));
|
||||
grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable));
|
||||
xsdt->oemrev = root_oemrev;
|
||||
grub_memcpy (&(xsdt->creator_id), root_creator_id, sizeof (xsdt->creator_id));
|
||||
xsdt->creator_rev = root_creator_rev;
|
||||
xsdt->checksum = 0;
|
||||
xsdt->checksum = 1 + ~grub_byte_checksum (xsdt, xsdt->length);
|
||||
|
||||
/* Create RSDPv2. */
|
||||
rsdpv2_new = (struct grub_acpi_rsdp_v20 *) playground_ptr;
|
||||
playground_ptr += sizeof (struct grub_acpi_rsdp_v20);
|
||||
grub_memcpy (&(rsdpv2_new->rsdpv1.signature), "RSD PTR ",
|
||||
sizeof (rsdpv2_new->rsdpv1.signature));
|
||||
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
|
||||
sizeof (rsdpv2_new->rsdpv1.oemid));
|
||||
rsdpv2_new->rsdpv1.revision = rev2;
|
||||
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv2_new->rsdpv1.checksum = 0;
|
||||
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
|
||||
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
|
||||
rsdpv2_new->length = sizeof (*rsdpv2_new);
|
||||
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt);
|
||||
rsdpv2_new->checksum = 0;
|
||||
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
|
||||
rsdpv2_new->length);
|
||||
grub_dprintf ("acpi", "Generated ACPIv2 tables\n");
|
||||
}
|
||||
|
||||
static void
|
||||
free_tables (void)
|
||||
{
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
if (table_dsdt)
|
||||
grub_free (table_dsdt);
|
||||
for (cur = acpi_tables; cur;)
|
||||
{
|
||||
t = cur;
|
||||
grub_free (cur->addr);
|
||||
cur = cur->next;
|
||||
grub_free (t);
|
||||
}
|
||||
acpi_tables = 0;
|
||||
table_dsdt = 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_acpi (struct grub_extcmd *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = cmd->state;
|
||||
struct grub_acpi_rsdp_v10 *rsdp;
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
grub_err_t err;
|
||||
int i, mmapregion;
|
||||
int numoftables;
|
||||
|
||||
/* Default values if no RSDP is found. */
|
||||
rev1 = 1;
|
||||
rev2 = 3;
|
||||
|
||||
facs_addr = 0;
|
||||
playground = playground_ptr = 0;
|
||||
playground_size = 0;
|
||||
|
||||
rsdp = (struct grub_acpi_rsdp_v10 *) grub_machine_acpi_get_rsdpv2 ();
|
||||
|
||||
if (! rsdp)
|
||||
rsdp = grub_machine_acpi_get_rsdpv1 ();
|
||||
|
||||
if (rsdp)
|
||||
{
|
||||
grub_uint32_t *entry_ptr;
|
||||
char *exclude = 0;
|
||||
char *load_only = 0;
|
||||
char *ptr;
|
||||
/* RSDT consists of header and an array of 32-bit pointers. */
|
||||
struct grub_acpi_table_header *rsdt;
|
||||
|
||||
exclude = state[0].set ? grub_strdup (state[0].arg) : 0;
|
||||
if (exclude)
|
||||
{
|
||||
for (ptr = exclude; *ptr; ptr++)
|
||||
*ptr = grub_tolower (*ptr);
|
||||
}
|
||||
|
||||
load_only = state[1].set ? grub_strdup (state[1].arg) : 0;
|
||||
if (load_only)
|
||||
{
|
||||
for (ptr = load_only; *ptr; ptr++)
|
||||
*ptr = grub_tolower (*ptr);
|
||||
}
|
||||
|
||||
/* Set revision variables to replicant the same version as host. */
|
||||
rev1 = ! rsdp->revision;
|
||||
rev2 = rsdp->revision;
|
||||
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr);
|
||||
/* Load host tables. */
|
||||
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
||||
+ rsdt->length);
|
||||
entry_ptr++)
|
||||
{
|
||||
char signature[5];
|
||||
struct efiemu_acpi_table *table;
|
||||
struct grub_acpi_table_header *curtable
|
||||
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr);
|
||||
signature[4] = 0;
|
||||
for (i = 0; i < 4;i++)
|
||||
signature[i] = grub_tolower (curtable->signature[i]);
|
||||
|
||||
/* If it's FADT it contains addresses of DSDT and FACS. */
|
||||
if (grub_strcmp (signature, "facp") == 0)
|
||||
{
|
||||
struct grub_acpi_table_header *dsdt;
|
||||
struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable;
|
||||
|
||||
/* Set root header variables to the same values
|
||||
as FACP by default. */
|
||||
grub_memcpy (&root_oemid, &(fadt->hdr.oemid),
|
||||
sizeof (root_oemid));
|
||||
grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable),
|
||||
sizeof (root_oemtable));
|
||||
root_oemrev = fadt->hdr.oemrev;
|
||||
grub_memcpy (&root_creator_id, &(fadt->hdr.creator_id),
|
||||
sizeof (root_creator_id));
|
||||
root_creator_rev = fadt->hdr.creator_rev;
|
||||
|
||||
/* Load DSDT if not excluded. */
|
||||
dsdt = (struct grub_acpi_table_header *)
|
||||
UINT_TO_PTR (fadt->dsdt_addr);
|
||||
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
|
||||
&& (! load_only || grub_strword (load_only, "dsdt"))
|
||||
&& dsdt->length >= sizeof (*dsdt))
|
||||
{
|
||||
dsdt_size = dsdt->length;
|
||||
table_dsdt = grub_malloc (dsdt->length);
|
||||
if (! table_dsdt)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Could allocate table");
|
||||
}
|
||||
grub_memcpy (table_dsdt, dsdt, dsdt->length);
|
||||
}
|
||||
|
||||
/* Save FACS address. FACS shouldn't be overriden. */
|
||||
facs_addr = fadt->facs_addr;
|
||||
}
|
||||
|
||||
/* Skip excluded tables. */
|
||||
if (exclude && grub_strword (exclude, signature))
|
||||
continue;
|
||||
if (load_only && ! grub_strword (load_only, signature))
|
||||
continue;
|
||||
|
||||
/* Sanity check. */
|
||||
if (curtable->length < sizeof (*curtable))
|
||||
continue;
|
||||
|
||||
table = (struct efiemu_acpi_table *) grub_malloc
|
||||
(sizeof (struct efiemu_acpi_table));
|
||||
if (! table)
|
||||
{
|
||||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Could allocate table structure");
|
||||
}
|
||||
table->size = curtable->length;
|
||||
table->addr = grub_malloc (table->size);
|
||||
playground_size += table->size;
|
||||
if (! table->addr)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Could allocate table");
|
||||
}
|
||||
table->next = acpi_tables;
|
||||
acpi_tables = table;
|
||||
grub_memcpy (table->addr, curtable, table->size);
|
||||
}
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
}
|
||||
|
||||
/* Does user specify versions to generate? */
|
||||
if (state[2].set || state[3].set)
|
||||
{
|
||||
rev1 = state[2].set;
|
||||
if (state[3].set)
|
||||
rev2 = rev2 ? : 2;
|
||||
else
|
||||
rev2 = 0;
|
||||
}
|
||||
|
||||
/* Does user override root header information? */
|
||||
if (state[4].set)
|
||||
grub_strncpy (root_oemid, state[4].arg, sizeof (root_oemid));
|
||||
if (state[5].set)
|
||||
grub_strncpy (root_oemtable, state[5].arg, sizeof (root_oemtable));
|
||||
if (state[6].set)
|
||||
root_oemrev = grub_strtoul (state[6].arg, 0, 0);
|
||||
if (state[7].set)
|
||||
grub_strncpy (root_creator_id, state[7].arg, sizeof (root_creator_id));
|
||||
if (state[8].set)
|
||||
root_creator_rev = grub_strtoul (state[8].arg, 0, 0);
|
||||
|
||||
/* Load user tables */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
grub_file_t file;
|
||||
grub_size_t size;
|
||||
char *buf;
|
||||
|
||||
file = grub_gzfile_open (args[i], 1);
|
||||
if (! file)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't open file %s", args[i]);
|
||||
}
|
||||
|
||||
size = grub_file_size (file);
|
||||
if (size < sizeof (struct grub_acpi_table_header))
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "file %s is too small", args[i]);
|
||||
}
|
||||
|
||||
buf = (char *) grub_malloc (size);
|
||||
if (! buf)
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't read file %s", args[i]);
|
||||
}
|
||||
|
||||
if (grub_file_read (file, buf, size) != (int) size)
|
||||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]);
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (grub_memcmp (((struct grub_acpi_table_header *) buf)->signature,
|
||||
"DSDT", 4) == 0)
|
||||
{
|
||||
grub_free (table_dsdt);
|
||||
table_dsdt = buf;
|
||||
dsdt_size = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct efiemu_acpi_table *table;
|
||||
table = (struct efiemu_acpi_table *) grub_malloc
|
||||
(sizeof (struct efiemu_acpi_table));
|
||||
if (! table)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Could allocate table structure");
|
||||
}
|
||||
|
||||
table->size = size;
|
||||
table->addr = buf;
|
||||
playground_size += table->size;
|
||||
}
|
||||
}
|
||||
|
||||
numoftables = 0;
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
numoftables++;
|
||||
|
||||
/* DSDT. */
|
||||
playground_size += dsdt_size;
|
||||
/* RSDT. */
|
||||
playground_size += sizeof (struct grub_acpi_table_header) + 4 * numoftables;
|
||||
/* RSDPv1. */
|
||||
playground_size += sizeof (struct grub_acpi_rsdp_v10);
|
||||
/* XSDT. */
|
||||
playground_size += sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
/* RSDPv2. */
|
||||
playground_size += sizeof (struct grub_acpi_rsdp_v20);
|
||||
|
||||
playground = playground_ptr
|
||||
= grub_mmap_malign_and_register (1, playground_size, &mmapregion,
|
||||
GRUB_MACHINE_MEMORY_ACPI, 0);
|
||||
|
||||
if (! playground)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Couldn't allocate space for ACPI tables");
|
||||
}
|
||||
|
||||
setup_common_tables ();
|
||||
|
||||
/* Request space for RSDPv1. */
|
||||
if (rev1)
|
||||
setv1table ();
|
||||
|
||||
/* Request space for RSDPv2+ and XSDT. */
|
||||
if (rev2)
|
||||
setv2table ();
|
||||
|
||||
for (cur = acpi_tables; cur;)
|
||||
{
|
||||
t = cur;
|
||||
cur = cur->next;
|
||||
grub_free (t);
|
||||
}
|
||||
acpi_tables = 0;
|
||||
|
||||
if (! state[9].set && (err = grub_acpi_create_ebda ()))
|
||||
{
|
||||
rsdpv1_new = 0;
|
||||
rsdpv2_new = 0;
|
||||
grub_mmap_free_and_unregister (mmapregion);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
{
|
||||
struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
|
||||
grub_efi_system_table->boot_services->install_configuration_table
|
||||
(&acpi20, grub_acpi_get_rsdpv2 ());
|
||||
grub_efi_system_table->boot_services->install_configuration_table
|
||||
(&acpi, grub_acpi_get_rsdpv1 ());
|
||||
}
|
||||
#endif
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(acpi)
|
||||
{
|
||||
(void) mod; /* To stop warning. */
|
||||
cmd = grub_register_extcmd ("acpi", grub_cmd_acpi,
|
||||
GRUB_COMMAND_FLAG_BOTH,
|
||||
"acpi [-1|-2] [--exclude=table1,table2|"
|
||||
"--load-only=table1,table2] filename1 "
|
||||
" [filename2] [...]",
|
||||
"Load host acpi tables and tables "
|
||||
"specified by arguments",
|
||||
options);
|
||||
my_mod=mod;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(acpi)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
}
|
59
commands/efi/acpi.c
Normal file
59
commands/efi/acpi.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* acpi.c - get acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/efi/api.h>
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_machine_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
{
|
||||
grub_efi_guid_t *guid =
|
||||
&grub_efi_system_table->configuration_table[i].vendor_guid;
|
||||
|
||||
if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v10 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_machine_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
unsigned i;
|
||||
static grub_efi_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
|
||||
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
|
||||
{
|
||||
grub_efi_guid_t *guid =
|
||||
&grub_efi_system_table->configuration_table[i].vendor_guid;
|
||||
|
||||
if (! grub_memcmp (guid, &acpi20_guid, sizeof (grub_efi_guid_t)))
|
||||
return (struct grub_acpi_rsdp_v20 *)
|
||||
grub_efi_system_table->configuration_table[i].vendor_table;
|
||||
}
|
||||
return 0;
|
||||
}
|
81
commands/i386/pc/acpi.c
Normal file
81
commands/i386/pc/acpi.c
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* acpi.c - get acpi tables. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
struct grub_acpi_rsdp_v10 *
|
||||
grub_machine_acpi_get_rsdpv1 (void)
|
||||
{
|
||||
int ebda_len;
|
||||
grub_uint8_t *ebda, *ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
|
||||
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
|
||||
ebda_len = * (grub_uint16_t *) ebda;
|
||||
if (! ebda_len)
|
||||
return 0;
|
||||
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
|
||||
return (struct grub_acpi_rsdp_v10 *) ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
|
||||
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
|
||||
ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0)
|
||||
return (struct grub_acpi_rsdp_v10 *) ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct grub_acpi_rsdp_v20 *
|
||||
grub_machine_acpi_get_rsdpv2 (void)
|
||||
{
|
||||
int ebda_len;
|
||||
grub_uint8_t *ebda, *ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n");
|
||||
ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4);
|
||||
ebda_len = * (grub_uint16_t *) ebda;
|
||||
if (! ebda_len)
|
||||
return 0;
|
||||
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
|
||||
&& grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
|
||||
== 0)
|
||||
return (struct grub_acpi_rsdp_v20 *) ptr;
|
||||
|
||||
grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n");
|
||||
for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000;
|
||||
ptr += 16)
|
||||
if (grub_memcmp (ptr, "RSD PTR ", 8) == 0
|
||||
&& grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0
|
||||
&& ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0
|
||||
&& ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024
|
||||
&& grub_byte_checksum (ptr, ((struct grub_acpi_rsdp_v20 *) ptr)->length)
|
||||
== 0)
|
||||
return (struct grub_acpi_rsdp_v20 *) ptr;
|
||||
return 0;
|
||||
}
|
|
@ -82,7 +82,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
|
|||
# Modules.
|
||||
pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
|
||||
linux.mod halt.mod reboot.mod pci.mod lspci.mod \
|
||||
datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod mmap.mod
|
||||
datetime.mod date.mod datehook.mod loadbios.mod \
|
||||
fixvideo.mod mmap.mod acpi.mod
|
||||
|
||||
# For kernel.mod.
|
||||
kernel_mod_EXPORTS = no
|
||||
|
@ -115,6 +116,11 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.
|
|||
kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
|
||||
/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
|
||||
|
||||
# For acpi.mod.
|
||||
acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c
|
||||
acpi_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
acpi_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
# For mmap.mod.
|
||||
mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
|
||||
mmap/efi/mmap.c
|
||||
|
|
|
@ -185,7 +185,12 @@ pkglib_MODULES = biosdisk.mod chain.mod \
|
|||
aout.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
|
||||
datehook.mod lsmmap.mod ata_pthru.mod hdparm.mod \
|
||||
usb.mod uhci.mod ohci.mod usbtest.mod usbms.mod usb_keyboard.mod \
|
||||
mmap.mod
|
||||
mmap.mod acpi.mod
|
||||
|
||||
# For acpi.mod.
|
||||
acpi_mod_SOURCES = commands/acpi.c commands/i386/pc/acpi.c
|
||||
acpi_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
acpi_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
# For mmap.mod.
|
||||
mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
|
||||
|
|
|
@ -80,7 +80,8 @@ grub_install_SOURCES = util/i386/efi/grub-install.in
|
|||
# Modules.
|
||||
pkglib_MODULES = kernel.mod chain.mod appleldr.mod \
|
||||
halt.mod reboot.mod linux.mod pci.mod lspci.mod \
|
||||
datetime.mod date.mod datehook.mod loadbios.mod fixvideo.mod mmap.mod
|
||||
datetime.mod date.mod datehook.mod loadbios.mod \
|
||||
fixvideo.mod mmap.mod acpi.mod
|
||||
|
||||
# For kernel.mod.
|
||||
kernel_mod_EXPORTS = no
|
||||
|
@ -114,6 +115,11 @@ symlist.c: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h gensymlist.
|
|||
kernel_syms.lst: $(addprefix include/grub/,$(kernel_mod_HEADERS)) config.h genkernsyms.sh
|
||||
/bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)
|
||||
|
||||
# For acpi.mod.
|
||||
acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c
|
||||
acpi_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
acpi_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
# For mmap.mod.
|
||||
mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \
|
||||
mmap/efi/mmap.c
|
||||
|
|
75
include/grub/acpi.h
Normal file
75
include/grub/acpi.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_ACPI_HEADER
|
||||
#define GRUB_ACPI_HEADER 1
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
|
||||
struct grub_acpi_rsdp_v10
|
||||
{
|
||||
grub_uint8_t signature[8];
|
||||
grub_uint8_t checksum;
|
||||
grub_uint8_t oemid[6];
|
||||
grub_uint8_t revision;
|
||||
grub_uint32_t rsdt_addr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_acpi_rsdp_v20
|
||||
{
|
||||
struct grub_acpi_rsdp_v10 rsdpv1;
|
||||
grub_uint32_t length;
|
||||
grub_uint64_t xsdt_addr;
|
||||
grub_uint8_t checksum;
|
||||
grub_uint8_t reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_acpi_table_header
|
||||
{
|
||||
grub_uint8_t signature[4];
|
||||
grub_uint32_t length;
|
||||
grub_uint8_t revision;
|
||||
grub_uint8_t checksum;
|
||||
grub_uint8_t oemid[6];
|
||||
grub_uint8_t oemtable[8];
|
||||
grub_uint32_t oemrev;
|
||||
grub_uint8_t creator_id[4];
|
||||
grub_uint32_t creator_rev;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_acpi_fadt
|
||||
{
|
||||
struct grub_acpi_table_header hdr;
|
||||
grub_uint32_t facs_addr;
|
||||
grub_uint32_t dsdt_addr;
|
||||
grub_uint8_t somefields1[88];
|
||||
grub_uint64_t facs_xaddr;
|
||||
grub_uint64_t dsdt_xaddr;
|
||||
grub_uint8_t somefields2[96];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void);
|
||||
struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void);
|
||||
struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void);
|
||||
struct grub_acpi_rsdp_v20 *grub_machine_acpi_get_rsdpv2 (void);
|
||||
grub_uint8_t grub_byte_checksum (void *base, grub_size_t size);
|
||||
|
||||
grub_err_t grub_acpi_create_ebda (void);
|
||||
|
||||
#endif /* ! GRUB_ACPI_HEADER */
|
Loading…
Reference in a new issue