1 /* acpi.c - modify acpi tables. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/extcmd.h>
22 #include <grub/file.h>
23 #include <grub/disk.h>
24 #include <grub/term.h>
25 #include <grub/misc.h>
26 #include <grub/acpi.h>
28 #include <grub/memory.h>
29 #include <grub/i18n.h>
31 #ifdef GRUB_MACHINE_EFI
32 #include <grub/efi/efi.h>
33 #include <grub/efi/api.h>
36 #pragma GCC diagnostic ignored "-Wcast-align"
38 GRUB_MOD_LICENSE ("GPLv3+");
40 static const struct grub_arg_option options
[] = {
42 N_("Don't load host tables specified by comma-separated list."),
45 N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING
},
46 {"v1", '1', 0, N_("Export version 1 tables to the OS."), 0, ARG_TYPE_NONE
},
47 {"v2", '2', 0, N_("Export version 2 and version 3 tables to the OS."), 0, ARG_TYPE_NONE
},
48 {"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
50 N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
51 {"oemtablerev", 'r', 0,
52 N_("Set OEMTABLE revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT
},
53 {"oemtablecreator", 'c', 0,
54 N_("Set creator field of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
55 {"oemtablecreatorrev", 'd', 0,
56 N_("Set creator revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT
},
57 /* TRANSLATORS: "hangs" here is a noun, not a verb. */
58 {"no-ebda", 'e', 0, N_("Don't update EBDA. May fix failures or hangs on some "
59 "BIOSes but makes it ineffective with OS not receiving RSDP from GRUB."),
64 /* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
66 grub_byte_checksum (void *base
, grub_size_t size
)
70 for (ptr
= (grub_uint8_t
*) base
; ptr
< ((grub_uint8_t
*) base
) + size
;
76 /* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
77 rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
78 static int rev1
, rev2
;
79 /* OEMID of RSDP, RSDT and XSDT. */
80 static char root_oemid
[6];
81 /* OEMTABLE of the same tables. */
82 static char root_oemtable
[8];
83 /* OEMREVISION of the same tables. */
84 static grub_uint32_t root_oemrev
;
85 /* CreatorID of the same tables. */
86 static char root_creator_id
[4];
87 /* CreatorRevision of the same tables. */
88 static grub_uint32_t root_creator_rev
;
89 static struct grub_acpi_rsdp_v10
*rsdpv1_new
= 0;
90 static struct grub_acpi_rsdp_v20
*rsdpv2_new
= 0;
91 static char *playground
= 0, *playground_ptr
= 0;
92 static int playground_size
= 0;
94 /* Linked list of ACPI tables. */
95 struct efiemu_acpi_table
99 struct efiemu_acpi_table
*next
;
101 static struct efiemu_acpi_table
*acpi_tables
= 0;
103 /* DSDT isn't in RSDT. So treat it specially. */
104 static void *table_dsdt
= 0;
105 /* Pointer to recreated RSDT. */
106 static void *rsdt_addr
= 0;
108 /* Allocation handles for different tables. */
109 static grub_size_t dsdt_size
= 0;
111 /* Address of original FACS. */
112 static grub_uint32_t facs_addr
= 0;
114 struct grub_acpi_rsdp_v20
*
115 grub_acpi_get_rsdpv2 (void)
121 return grub_machine_acpi_get_rsdpv2 ();
124 struct grub_acpi_rsdp_v10
*
125 grub_acpi_get_rsdpv1 (void)
131 return grub_machine_acpi_get_rsdpv1 ();
135 iszero (grub_uint8_t
*reg
, int size
)
138 for (i
= 0; i
< size
; i
++)
144 #if defined (__i386__) || defined (__x86_64__)
146 grub_acpi_create_ebda (void)
151 grub_uint8_t
*ebda
, *v1inebda
= 0, *v2inebda
= 0;
152 grub_uint64_t highestlow
= 0;
153 grub_uint8_t
*targetebda
, *target
;
154 struct grub_acpi_rsdp_v10
*v1
;
155 struct grub_acpi_rsdp_v20
*v2
;
156 auto int NESTED_FUNC_ATTR
find_hook (grub_uint64_t
, grub_uint64_t
,
158 int NESTED_FUNC_ATTR
find_hook (grub_uint64_t start
, grub_uint64_t size
,
159 grub_memory_type_t type
)
161 grub_uint64_t end
= start
+ size
;
162 if (type
!= GRUB_MEMORY_AVAILABLE
)
166 if (end
> start
+ ebda_len
167 && highestlow
< ((end
- ebda_len
) & (~0xf)) )
168 highestlow
= (end
- ebda_len
) & (~0xf);
172 ebda
= (grub_uint8_t
*) (grub_addr_t
) ((*((grub_uint16_t
*)0x40e)) << 4);
173 ebda_kb_len
= *(grub_uint16_t
*) ebda
;
174 if (! ebda
|| ebda_kb_len
> 16)
176 ebda_len
= (ebda_kb_len
+ 1) << 10;
178 /* FIXME: use low-memory mm allocation once it's available. */
179 grub_mmap_iterate (find_hook
);
180 targetebda
= (grub_uint8_t
*) (grub_addr_t
) highestlow
;
181 grub_dprintf ("acpi", "creating ebda @%llx\n",
182 (unsigned long long) highestlow
);
184 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
185 "couldn't find space for the new EBDA");
187 mmapregion
= grub_mmap_register ((grub_addr_t
) targetebda
, ebda_len
,
188 GRUB_MEMORY_RESERVED
);
192 /* XXX: EBDA is unstandardized, so this implementation is heuristical. */
194 grub_memcpy (targetebda
, ebda
, 0x400);
196 grub_memset (targetebda
, 0, 0x400);
197 *((grub_uint16_t
*) targetebda
) = ebda_kb_len
+ 1;
200 v1
= grub_acpi_get_rsdpv1 ();
201 v2
= grub_acpi_get_rsdpv2 ();
202 if (v2
&& v2
->length
> 40)
205 /* First try to replace already existing rsdp. */
208 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
209 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
210 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
211 && grub_byte_checksum (target
,
212 sizeof (struct grub_acpi_rsdp_v10
)) == 0
213 && ((struct grub_acpi_rsdp_v10
*) target
)->revision
!= 0
214 && ((struct grub_acpi_rsdp_v20
*) target
)->length
<= v2
->length
)
216 grub_memcpy (target
, v2
, v2
->length
);
217 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
219 target
+= v2
->length
;
220 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
228 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
229 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
231 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
232 && grub_byte_checksum (target
,
233 sizeof (struct grub_acpi_rsdp_v10
)) == 0)
235 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
236 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
238 target
+= sizeof (struct grub_acpi_rsdp_v10
);
239 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
245 target
= targetebda
+ 0x100;
247 /* Try contiguous zeros. */
250 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
251 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
252 if (iszero (target
, v2
->length
))
254 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
255 grub_memcpy (target
, v2
, v2
->length
);
257 target
+= v2
->length
;
258 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
266 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
267 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
269 if (iszero (target
, sizeof (struct grub_acpi_rsdp_v10
)))
271 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
272 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
274 target
+= sizeof (struct grub_acpi_rsdp_v10
);
275 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
283 grub_mmap_unregister (mmapregion
);
284 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
285 "couldn't find suitable spot in EBDA");
288 /* Remove any other RSDT. */
289 for (target
= targetebda
;
290 target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
292 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
293 && grub_byte_checksum (target
,
294 sizeof (struct grub_acpi_rsdp_v10
)) == 0
295 && target
!= v1inebda
&& target
!= v2inebda
)
298 grub_dprintf ("acpi", "Switching EBDA\n");
299 (*((grub_uint16_t
*) 0x40e)) = ((long)targetebda
) >> 4;
300 grub_dprintf ("acpi", "EBDA switched\n");
302 return GRUB_ERR_NONE
;
306 /* Create tables common to ACPIv1 and ACPIv2+ */
308 setup_common_tables (void)
310 struct efiemu_acpi_table
*cur
;
311 struct grub_acpi_table_header
*rsdt
;
312 grub_uint32_t
*rsdt_entry
;
316 grub_memcpy (playground_ptr
, table_dsdt
, dsdt_size
);
317 grub_free (table_dsdt
);
318 table_dsdt
= playground_ptr
;
319 playground_ptr
+= dsdt_size
;
321 /* Treat other tables. */
322 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
324 struct grub_acpi_fadt
*fadt
;
326 grub_memcpy (playground_ptr
, cur
->addr
, cur
->size
);
327 grub_free (cur
->addr
);
328 cur
->addr
= playground_ptr
;
329 playground_ptr
+= cur
->size
;
331 /* If it's FADT correct DSDT and FACS addresses. */
332 fadt
= (struct grub_acpi_fadt
*) cur
->addr
;
333 if (grub_memcmp (fadt
->hdr
.signature
, GRUB_ACPI_FADT_SIGNATURE
,
334 sizeof (fadt
->hdr
.signature
)) == 0)
336 fadt
->dsdt_addr
= (grub_addr_t
) table_dsdt
;
337 fadt
->facs_addr
= facs_addr
;
339 /* Does a revision 2 exist at all? */
340 if (fadt
->hdr
.revision
>= 3)
342 fadt
->dsdt_xaddr
= (grub_addr_t
) table_dsdt
;
343 fadt
->facs_xaddr
= facs_addr
;
346 /* Recompute checksum. */
347 fadt
->hdr
.checksum
= 0;
348 fadt
->hdr
.checksum
= 1 + ~grub_byte_checksum (fadt
, fadt
->hdr
.length
);
352 /* Fill RSDT entries. */
354 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
357 rsdt_addr
= rsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
358 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
360 rsdt_entry
= (grub_uint32_t
*) (rsdt
+ 1);
362 /* Fill RSDT header. */
363 grub_memcpy (&(rsdt
->signature
), "RSDT", 4);
364 rsdt
->length
= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
366 grub_memcpy (&(rsdt
->oemid
), root_oemid
, sizeof (rsdt
->oemid
));
367 grub_memcpy (&(rsdt
->oemtable
), root_oemtable
, sizeof (rsdt
->oemtable
));
368 rsdt
->oemrev
= root_oemrev
;
369 grub_memcpy (&(rsdt
->creator_id
), root_creator_id
, sizeof (rsdt
->creator_id
));
370 rsdt
->creator_rev
= root_creator_rev
;
372 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
373 *(rsdt_entry
++) = (grub_addr_t
) cur
->addr
;
375 /* Recompute checksum. */
377 rsdt
->checksum
= 1 + ~grub_byte_checksum (rsdt
, rsdt
->length
);
380 /* Regenerate ACPIv1 RSDP */
385 rsdpv1_new
= (struct grub_acpi_rsdp_v10
*) playground_ptr
;
386 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v10
);
387 grub_memcpy (&(rsdpv1_new
->signature
), "RSD PTR ",
388 sizeof (rsdpv1_new
->signature
));
389 grub_memcpy (&(rsdpv1_new
->oemid
), root_oemid
, sizeof (rsdpv1_new
->oemid
));
390 rsdpv1_new
->revision
= 0;
391 rsdpv1_new
->rsdt_addr
= (grub_addr_t
) rsdt_addr
;
392 rsdpv1_new
->checksum
= 0;
393 rsdpv1_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv1_new
,
394 sizeof (*rsdpv1_new
));
395 grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
401 struct grub_acpi_table_header
*xsdt
;
402 struct efiemu_acpi_table
*cur
;
403 grub_uint64_t
*xsdt_entry
;
407 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
411 xsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
412 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
414 xsdt_entry
= (grub_uint64_t
*)(xsdt
+ 1);
415 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
416 *(xsdt_entry
++) = (grub_addr_t
) cur
->addr
;
417 grub_memcpy (&(xsdt
->signature
), "XSDT", 4);
418 xsdt
->length
= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
420 grub_memcpy (&(xsdt
->oemid
), root_oemid
, sizeof (xsdt
->oemid
));
421 grub_memcpy (&(xsdt
->oemtable
), root_oemtable
, sizeof (xsdt
->oemtable
));
422 xsdt
->oemrev
= root_oemrev
;
423 grub_memcpy (&(xsdt
->creator_id
), root_creator_id
, sizeof (xsdt
->creator_id
));
424 xsdt
->creator_rev
= root_creator_rev
;
426 xsdt
->checksum
= 1 + ~grub_byte_checksum (xsdt
, xsdt
->length
);
429 rsdpv2_new
= (struct grub_acpi_rsdp_v20
*) playground_ptr
;
430 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v20
);
431 grub_memcpy (&(rsdpv2_new
->rsdpv1
.signature
), "RSD PTR ",
432 sizeof (rsdpv2_new
->rsdpv1
.signature
));
433 grub_memcpy (&(rsdpv2_new
->rsdpv1
.oemid
), root_oemid
,
434 sizeof (rsdpv2_new
->rsdpv1
.oemid
));
435 rsdpv2_new
->rsdpv1
.revision
= rev2
;
436 rsdpv2_new
->rsdpv1
.rsdt_addr
= (grub_addr_t
) rsdt_addr
;
437 rsdpv2_new
->rsdpv1
.checksum
= 0;
438 rsdpv2_new
->rsdpv1
.checksum
= 1 + ~grub_byte_checksum
439 (&(rsdpv2_new
->rsdpv1
), sizeof (rsdpv2_new
->rsdpv1
));
440 rsdpv2_new
->length
= sizeof (*rsdpv2_new
);
441 rsdpv2_new
->xsdt_addr
= (grub_addr_t
) xsdt
;
442 rsdpv2_new
->checksum
= 0;
443 rsdpv2_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv2_new
,
445 grub_dprintf ("acpi", "Generated ACPIv2 tables\n");
451 struct efiemu_acpi_table
*cur
, *t
;
453 grub_free (table_dsdt
);
454 for (cur
= acpi_tables
; cur
;)
457 grub_free (cur
->addr
);
466 grub_cmd_acpi (struct grub_extcmd_context
*ctxt
, int argc
, char **args
)
468 struct grub_arg_list
*state
= ctxt
->state
;
469 struct grub_acpi_rsdp_v10
*rsdp
;
470 struct efiemu_acpi_table
*cur
, *t
;
474 /* Default values if no RSDP is found. */
479 playground
= playground_ptr
= 0;
482 rsdp
= (struct grub_acpi_rsdp_v10
*) grub_machine_acpi_get_rsdpv2 ();
485 rsdp
= grub_machine_acpi_get_rsdpv1 ();
489 grub_uint32_t
*entry_ptr
;
493 /* RSDT consists of header and an array of 32-bit pointers. */
494 struct grub_acpi_table_header
*rsdt
;
496 exclude
= state
[0].set
? grub_strdup (state
[0].arg
) : 0;
499 for (ptr
= exclude
; *ptr
; ptr
++)
500 *ptr
= grub_tolower (*ptr
);
503 load_only
= state
[1].set
? grub_strdup (state
[1].arg
) : 0;
506 for (ptr
= load_only
; *ptr
; ptr
++)
507 *ptr
= grub_tolower (*ptr
);
510 /* Set revision variables to replicate the same version as host. */
511 rev1
= ! rsdp
->revision
;
512 rev2
= rsdp
->revision
;
513 rsdt
= (struct grub_acpi_table_header
*) (grub_addr_t
) rsdp
->rsdt_addr
;
514 /* Load host tables. */
515 for (entry_ptr
= (grub_uint32_t
*) (rsdt
+ 1);
516 entry_ptr
< (grub_uint32_t
*) (((grub_uint8_t
*) rsdt
)
521 struct efiemu_acpi_table
*table
;
522 struct grub_acpi_table_header
*curtable
523 = (struct grub_acpi_table_header
*) (grub_addr_t
) *entry_ptr
;
525 for (i
= 0; i
< 4;i
++)
526 signature
[i
] = grub_tolower (curtable
->signature
[i
]);
528 /* If it's FADT it contains addresses of DSDT and FACS. */
529 if (grub_strcmp (signature
, "facp") == 0)
531 struct grub_acpi_table_header
*dsdt
;
532 struct grub_acpi_fadt
*fadt
= (struct grub_acpi_fadt
*) curtable
;
534 /* Set root header variables to the same values
535 as FADT by default. */
536 grub_memcpy (&root_oemid
, &(fadt
->hdr
.oemid
),
537 sizeof (root_oemid
));
538 grub_memcpy (&root_oemtable
, &(fadt
->hdr
.oemtable
),
539 sizeof (root_oemtable
));
540 root_oemrev
= fadt
->hdr
.oemrev
;
541 grub_memcpy (&root_creator_id
, &(fadt
->hdr
.creator_id
),
542 sizeof (root_creator_id
));
543 root_creator_rev
= fadt
->hdr
.creator_rev
;
545 /* Load DSDT if not excluded. */
546 dsdt
= (struct grub_acpi_table_header
*)
547 (grub_addr_t
) fadt
->dsdt_addr
;
548 if (dsdt
&& (! exclude
|| ! grub_strword (exclude
, "dsdt"))
549 && (! load_only
|| grub_strword (load_only
, "dsdt"))
550 && dsdt
->length
>= sizeof (*dsdt
))
552 dsdt_size
= dsdt
->length
;
553 table_dsdt
= grub_malloc (dsdt
->length
);
558 grub_free (load_only
);
561 grub_memcpy (table_dsdt
, dsdt
, dsdt
->length
);
564 /* Save FACS address. FACS shouldn't be overridden. */
565 facs_addr
= fadt
->facs_addr
;
568 /* Skip excluded tables. */
569 if (exclude
&& grub_strword (exclude
, signature
))
571 if (load_only
&& ! grub_strword (load_only
, signature
))
575 if (curtable
->length
< sizeof (*curtable
))
578 table
= (struct efiemu_acpi_table
*) grub_malloc
579 (sizeof (struct efiemu_acpi_table
));
584 grub_free (load_only
);
587 table
->size
= curtable
->length
;
588 table
->addr
= grub_malloc (table
->size
);
589 playground_size
+= table
->size
;
595 table
->next
= acpi_tables
;
597 grub_memcpy (table
->addr
, curtable
, table
->size
);
600 grub_free (load_only
);
603 /* Does user specify versions to generate? */
604 if (state
[2].set
|| state
[3].set
)
613 /* Does user override root header information? */
615 grub_strncpy (root_oemid
, state
[4].arg
, sizeof (root_oemid
));
617 grub_strncpy (root_oemtable
, state
[5].arg
, sizeof (root_oemtable
));
619 root_oemrev
= grub_strtoul (state
[6].arg
, 0, 0);
621 grub_strncpy (root_creator_id
, state
[7].arg
, sizeof (root_creator_id
));
623 root_creator_rev
= grub_strtoul (state
[8].arg
, 0, 0);
625 /* Load user tables */
626 for (i
= 0; i
< argc
; i
++)
632 file
= grub_file_open (args
[i
]);
639 size
= grub_file_size (file
);
640 if (size
< sizeof (struct grub_acpi_table_header
))
642 grub_file_close (file
);
644 return grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
648 buf
= (char *) grub_malloc (size
);
651 grub_file_close (file
);
656 if (grub_file_read (file
, buf
, size
) != (int) size
)
658 grub_file_close (file
);
661 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
665 grub_file_close (file
);
667 if (grub_memcmp (((struct grub_acpi_table_header
*) buf
)->signature
,
670 grub_free (table_dsdt
);
676 struct efiemu_acpi_table
*table
;
677 table
= (struct efiemu_acpi_table
*) grub_malloc
678 (sizeof (struct efiemu_acpi_table
));
687 playground_size
+= table
->size
;
689 table
->next
= acpi_tables
;
695 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
699 playground_size
+= dsdt_size
;
701 playground_size
+= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
703 playground_size
+= sizeof (struct grub_acpi_rsdp_v10
);
705 playground_size
+= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
707 playground_size
+= sizeof (struct grub_acpi_rsdp_v20
);
709 playground
= playground_ptr
710 = grub_mmap_malign_and_register (1, playground_size
, &mmapregion
,
711 GRUB_MEMORY_ACPI
, 0);
716 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
717 "couldn't allocate space for ACPI tables");
720 setup_common_tables ();
722 /* Request space for RSDPv1. */
726 /* Request space for RSDPv2+ and XSDT. */
730 for (cur
= acpi_tables
; cur
;)
738 #if defined (__i386__) || defined (__x86_64__)
742 err
= grub_acpi_create_ebda ();
747 grub_mmap_free_and_unregister (mmapregion
);
753 #ifdef GRUB_MACHINE_EFI
755 struct grub_efi_guid acpi
= GRUB_EFI_ACPI_TABLE_GUID
;
756 struct grub_efi_guid acpi20
= GRUB_EFI_ACPI_20_TABLE_GUID
;
758 grub_efi_system_table
->boot_services
->install_configuration_table
759 (&acpi20
, grub_acpi_get_rsdpv2 ());
760 grub_efi_system_table
->boot_services
->install_configuration_table
761 (&acpi
, grub_acpi_get_rsdpv1 ());
765 return GRUB_ERR_NONE
;
768 static grub_extcmd_t cmd
;
772 cmd
= grub_register_extcmd ("acpi", grub_cmd_acpi
, 0,
773 N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
774 "--load-only=TABLE1,TABLE2] FILE1"
776 N_("Load host ACPI tables and tables "
777 "specified by arguments."),
783 grub_unregister_extcmd (cmd
);