]> git.proxmox.com Git - grub2.git/blob - grub-core/kern/acpi.c
Make grub_acpi_find_fadt accessible generically
[grub2.git] / grub-core / kern / acpi.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2012 Free Software Foundation, Inc.
4 *
5 * GRUB 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, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <grub/types.h>
20 #include <grub/time.h>
21 #include <grub/misc.h>
22 #include <grub/acpi.h>
23
24 /* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
25 grub_uint8_t
26 grub_byte_checksum (void *base, grub_size_t size)
27 {
28 grub_uint8_t *ptr;
29 grub_uint8_t ret = 0;
30 for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
31 ptr++)
32 ret += *ptr;
33 return ret;
34 }
35
36 static void *
37 grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
38 {
39 grub_size_t s;
40 grub_unaligned_uint32_t *ptr;
41
42 if (!rsdt)
43 return 0;
44
45 if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
46 return 0;
47
48 ptr = (grub_unaligned_uint32_t *) (rsdt + 1);
49 s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
50 for (; s; s--, ptr++)
51 {
52 struct grub_acpi_table_header *tbl;
53 tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
54 if (grub_memcmp (tbl->signature, sig, 4) == 0)
55 return tbl;
56 }
57 return 0;
58 }
59
60 static void *
61 grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
62 {
63 grub_size_t s;
64 grub_unaligned_uint64_t *ptr;
65
66 if (!xsdt)
67 return 0;
68
69 if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
70 return 0;
71
72 ptr = (grub_unaligned_uint64_t *) (xsdt + 1);
73 s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
74 for (; s; s--, ptr++)
75 {
76 struct grub_acpi_table_header *tbl;
77 #if GRUB_CPU_SIZEOF_VOID_P != 8
78 if (ptr->val >> 32)
79 continue;
80 #endif
81 tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
82 if (grub_memcmp (tbl->signature, sig, 4) == 0)
83 return tbl;
84 }
85 return 0;
86 }
87
88 struct grub_acpi_fadt *
89 grub_acpi_find_fadt (void)
90 {
91 struct grub_acpi_fadt *fadt = 0;
92 struct grub_acpi_rsdp_v10 *rsdpv1;
93 struct grub_acpi_rsdp_v20 *rsdpv2;
94 rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
95 if (rsdpv1)
96 fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
97 (grub_addr_t) rsdpv1->rsdt_addr,
98 GRUB_ACPI_FADT_SIGNATURE);
99 if (fadt)
100 return fadt;
101 rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
102 if (rsdpv2)
103 fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
104 (grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
105 GRUB_ACPI_FADT_SIGNATURE);
106 if (fadt)
107 return fadt;
108 if (rsdpv2
109 #if GRUB_CPU_SIZEOF_VOID_P != 8
110 && !(rsdpv2->xsdt_addr >> 32)
111 #endif
112 )
113 fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
114 (grub_addr_t) rsdpv2->xsdt_addr,
115 GRUB_ACPI_FADT_SIGNATURE);
116 if (fadt)
117 return fadt;
118 return 0;
119 }