1 /* ----------------------------------------------------------------------- *
3 * Copyright 2010 Intel Corporation; author: H. Peter Anvin
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8 * Boston MA 02110-1301, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
14 * Dump ACPI information
24 uint8_t magic
[8]; /* "RSD PTR " */
36 char sig
[4]; /* Signature */
53 ERR_NONE
, /* No errors */
54 ERR_CSUM
, /* Invalid checksum */
55 ERR_SIZE
, /* Impossibly large table */
56 ERR_NOSIG
/* No signature */
59 static uint8_t checksum_range(const void *start
, uint32_t size
)
61 const uint8_t *p
= start
;
70 static enum tbl_errs
is_valid_table(const void *ptr
)
72 const struct acpi_hdr
*hdr
= ptr
;
77 if (hdr
->len
< 10 || hdr
->len
> (1 << 20)) {
78 /* Either insane or too large to dump */
82 return checksum_range(hdr
, hdr
->len
) == 0 ? ERR_NONE
: ERR_CSUM
;
85 static const struct acpi_rsdp
*scan_for_rsdp(uint32_t base
, uint32_t end
)
87 for (base
&= ~15; base
< end
-20; base
+= 16) {
88 const struct acpi_rsdp
*rsdp
= (const struct acpi_rsdp
*)base
;
90 if (memcmp(rsdp
->magic
, "RSD PTR ", 8))
93 if (checksum_range(rsdp
, 20))
97 if (base
+ rsdp
->len
>= end
||
98 checksum_range(rsdp
, rsdp
->len
))
108 static const struct acpi_rsdp
*find_rsdp(void)
111 const struct acpi_rsdp
*rsdp
;
113 ebda
= (*(uint16_t *)0x40e) << 4;
114 if (ebda
>= 0x70000 && ebda
< 0xa0000) {
115 rsdp
= scan_for_rsdp(ebda
, ebda
+1024);
121 return scan_for_rsdp(0xe0000, 0x100000);
124 static void dump_table(struct backend
*be
,
125 const char name
[], const void *ptr
, uint32_t len
)
129 /* XXX: this make cause the same directory to show up more than once */
130 snprintf(namebuf
, sizeof namebuf
, "acpi/%4.4s", name
);
131 cpio_mkdir(be
, namebuf
);
133 snprintf(namebuf
, sizeof namebuf
, "acpi/%4.4s/%08x", name
, (uint32_t)ptr
);
134 cpio_hdr(be
, MODE_FILE
, len
, namebuf
);
136 write_data(be
, ptr
, len
);
139 void dump_acpi(struct backend
*be
)
141 const struct acpi_rsdp
*rsdp
;
142 const struct acpi_rsdt
*rsdt
;
149 return; /* No ACPI information found */
151 cpio_mkdir(be
, "acpi");
153 rsdp_len
= rsdp
->rev
> 0 ? rsdp
->len
: 20;
155 dump_table(be
, "RSDP", rsdp
, rsdp_len
);
157 rsdt
= (const struct acpi_rsdt
*)rsdp
->rsdt_addr
;
159 if (memcmp(rsdt
->hdr
.sig
, "RSDT", 4) || is_valid_table(rsdt
) != ERR_NONE
)
162 dump_table(be
, rsdt
->hdr
.sig
, rsdt
, rsdt
->hdr
.len
);
164 if (rsdt
->hdr
.len
< 36)
167 n
= (rsdt
->hdr
.len
- 36) >> 2;
169 for (i
= 0; i
< n
; i
++) {
170 const struct acpi_hdr
*hdr
= (const struct acpi_hdr
*)(rsdt
->entry
[i
]);
172 if (is_valid_table(hdr
) <= ERR_CSUM
)
173 dump_table(be
, hdr
->sig
, hdr
, hdr
->len
);