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/gzio.h>
27 #include <grub/acpi.h>
29 #include <grub/machine/memory.h>
30 #include <grub/memory.h>
31 #include <grub/i18n.h>
33 #ifdef GRUB_MACHINE_EFI
34 #include <grub/efi/efi.h>
35 #include <grub/efi/api.h>
38 static const struct grub_arg_option options
[] = {
40 N_("Don't load host tables specified by comma-separated list."),
43 N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING
},
44 {"v1", '1', 0, N_("Expose v1 tables."), 0, ARG_TYPE_NONE
},
45 {"v2", '2', 0, N_("Expose v2 and v3 tables."), 0, ARG_TYPE_NONE
},
46 {"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
48 N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
49 {"oemtablerev", 'r', 0,
50 N_("Set OEMTABLE revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT
},
51 {"oemtablecreator", 'c', 0,
52 N_("Set creator field of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING
},
53 {"oemtablecreatorrev", 'd', 0,
54 N_("Set creator revision of RSDP, XSDT and RSDT."), 0, ARG_TYPE_INT
},
55 {"no-ebda", 'e', 0, N_("Don't update EBDA. May fix failures or hangs on some."
56 " BIOSes but makes it ineffective with OS not receiving RSDP from GRUB."),
61 /* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
63 grub_byte_checksum (void *base
, grub_size_t size
)
67 for (ptr
= (grub_uint8_t
*) base
; ptr
< ((grub_uint8_t
*) base
) + size
;
73 /* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
74 rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
75 static int rev1
, rev2
;
76 /* OEMID of RSDP, RSDT and XSDT. */
77 static char root_oemid
[6];
78 /* OEMTABLE of the same tables. */
79 static char root_oemtable
[8];
80 /* OEMREVISION of the same tables. */
81 static grub_uint32_t root_oemrev
;
82 /* CreatorID of the same tables. */
83 static char root_creator_id
[4];
84 /* CreatorRevision of the same tables. */
85 static grub_uint32_t root_creator_rev
;
86 static struct grub_acpi_rsdp_v10
*rsdpv1_new
= 0;
87 static struct grub_acpi_rsdp_v20
*rsdpv2_new
= 0;
88 static char *playground
= 0, *playground_ptr
= 0;
89 static int playground_size
= 0;
91 /* Linked list of ACPI tables. */
92 struct efiemu_acpi_table
96 struct efiemu_acpi_table
*next
;
98 static struct efiemu_acpi_table
*acpi_tables
= 0;
100 /* DSDT isn't in RSDT. So treat it specially. */
101 static void *table_dsdt
= 0;
102 /* Pointer to recreated RSDT. */
103 static void *rsdt_addr
= 0;
105 /* Allocation handles for different tables. */
106 static grub_size_t dsdt_size
= 0;
108 /* Address of original FACS. */
109 static grub_uint32_t facs_addr
= 0;
111 struct grub_acpi_rsdp_v20
*
112 grub_acpi_get_rsdpv2 (void)
118 return grub_machine_acpi_get_rsdpv2 ();
121 struct grub_acpi_rsdp_v10
*
122 grub_acpi_get_rsdpv1 (void)
128 return grub_machine_acpi_get_rsdpv1 ();
132 iszero (grub_uint8_t
*reg
, int size
)
135 for (i
= 0; i
< size
; i
++)
142 grub_acpi_create_ebda (void)
147 grub_uint8_t
*ebda
, *v1inebda
= 0, *v2inebda
= 0;
148 grub_uint64_t highestlow
= 0;
149 grub_uint8_t
*targetebda
, *target
;
150 struct grub_acpi_rsdp_v10
*v1
;
151 struct grub_acpi_rsdp_v20
*v2
;
152 auto int NESTED_FUNC_ATTR
find_hook (grub_uint64_t
, grub_uint64_t
,
154 int NESTED_FUNC_ATTR
find_hook (grub_uint64_t start
, grub_uint64_t size
,
157 grub_uint64_t end
= start
+ size
;
158 if (type
!= GRUB_MACHINE_MEMORY_AVAILABLE
)
162 if (end
> start
+ ebda_len
163 && highestlow
< ((end
- ebda_len
) & (~0xf)) )
164 highestlow
= (end
- ebda_len
) & (~0xf);
168 ebda
= (grub_uint8_t
*) UINT_TO_PTR ((*((grub_uint16_t
*)0x40e)) << 4);
169 ebda_kb_len
= *(grub_uint16_t
*) ebda
;
170 if (! ebda
|| ebda_kb_len
> 16)
172 ebda_len
= (ebda_kb_len
+ 1) << 10;
174 /* FIXME: use low-memory mm allocation once it's available. */
175 grub_mmap_iterate (find_hook
);
176 targetebda
= (grub_uint8_t
*) UINT_TO_PTR (highestlow
);
177 grub_dprintf ("acpi", "creating ebda @%llx\n",
178 (unsigned long long) highestlow
);
180 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
181 "couldn't find space for the new EBDA");
183 mmapregion
= grub_mmap_register (PTR_TO_UINT64 (targetebda
), ebda_len
,
184 GRUB_MACHINE_MEMORY_RESERVED
);
188 /* XXX: EBDA is unstandardized, so this implementation is heuristical. */
190 grub_memcpy (targetebda
, ebda
, 0x400);
192 grub_memset (targetebda
, 0, 0x400);
193 *((grub_uint16_t
*) targetebda
) = ebda_kb_len
+ 1;
196 v1
= grub_acpi_get_rsdpv1 ();
197 v2
= grub_acpi_get_rsdpv2 ();
198 if (v2
&& v2
->length
> 40)
201 /* First try to replace already existing rsdp. */
204 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
205 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
206 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
207 && grub_byte_checksum (target
,
208 sizeof (struct grub_acpi_rsdp_v10
)) == 0
209 && ((struct grub_acpi_rsdp_v10
*) target
)->revision
!= 0
210 && ((struct grub_acpi_rsdp_v20
*) target
)->length
<= v2
->length
)
212 grub_memcpy (target
, v2
, v2
->length
);
213 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
215 target
+= v2
->length
;
216 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
224 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
225 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
227 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
228 && grub_byte_checksum (target
,
229 sizeof (struct grub_acpi_rsdp_v10
)) == 0)
231 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
232 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
234 target
+= sizeof (struct grub_acpi_rsdp_v10
);
235 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
241 target
= targetebda
+ 0x100;
243 /* Try contiguous zeros. */
246 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
247 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
248 if (iszero (target
, v2
->length
))
250 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
251 grub_memcpy (target
, v2
, v2
->length
);
253 target
+= v2
->length
;
254 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
262 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
263 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
265 if (iszero (target
, sizeof (struct grub_acpi_rsdp_v10
)))
267 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
268 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
270 target
+= sizeof (struct grub_acpi_rsdp_v10
);
271 target
= (grub_uint8_t
*) ((((long) target
- 1) | 0xf) + 1);
279 grub_mmap_unregister (mmapregion
);
280 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
281 "couldn't find suitable spot in EBDA");
284 /* Remove any other RSDT. */
285 for (target
= targetebda
;
286 target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
288 if (grub_memcmp (target
, "RSD PTR ", 8) == 0
289 && grub_byte_checksum (target
,
290 sizeof (struct grub_acpi_rsdp_v10
)) == 0
291 && target
!= v1inebda
&& target
!= v2inebda
)
294 grub_dprintf ("acpi", "Switching EBDA\n");
295 (*((grub_uint16_t
*) 0x40e)) = ((long)targetebda
) >> 4;
296 grub_dprintf ("acpi", "EBDA switched\n");
298 return GRUB_ERR_NONE
;
301 /* Create tables common to ACPIv1 and ACPIv2+ */
303 setup_common_tables (void)
305 struct efiemu_acpi_table
*cur
;
306 struct grub_acpi_table_header
*rsdt
;
307 grub_uint32_t
*rsdt_entry
;
311 grub_memcpy (playground_ptr
, table_dsdt
, dsdt_size
);
312 grub_free (table_dsdt
);
313 table_dsdt
= playground_ptr
;
314 playground_ptr
+= dsdt_size
;
316 /* Treat other tables. */
317 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
319 struct grub_acpi_fadt
*fadt
;
321 grub_memcpy (playground_ptr
, cur
->addr
, cur
->size
);
322 grub_free (cur
->addr
);
323 cur
->addr
= playground_ptr
;
324 playground_ptr
+= cur
->size
;
326 /* If it's FADT correct DSDT and FACS addresses. */
327 fadt
= (struct grub_acpi_fadt
*) cur
->addr
;
328 if (grub_memcmp (fadt
->hdr
.signature
, "FACP", 4) == 0)
330 fadt
->dsdt_addr
= PTR_TO_UINT32 (table_dsdt
);
331 fadt
->facs_addr
= facs_addr
;
333 /* Does a revision 2 exist at all? */
334 if (fadt
->hdr
.revision
>= 3)
336 fadt
->dsdt_xaddr
= PTR_TO_UINT64 (table_dsdt
);
337 fadt
->facs_xaddr
= facs_addr
;
340 /* Recompute checksum. */
341 fadt
->hdr
.checksum
= 0;
342 fadt
->hdr
.checksum
= 1 + ~grub_byte_checksum (fadt
, fadt
->hdr
.length
);
346 /* Fill RSDT entries. */
348 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
351 rsdt_addr
= rsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
352 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
354 rsdt_entry
= (grub_uint32_t
*)(rsdt
+ 1);
356 /* Fill RSDT header. */
357 grub_memcpy (&(rsdt
->signature
), "RSDT", 4);
358 rsdt
->length
= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
360 grub_memcpy (&(rsdt
->oemid
), root_oemid
, 6);
361 grub_memcpy (&(rsdt
->oemtable
), root_oemtable
, 4);
362 rsdt
->oemrev
= root_oemrev
;
363 grub_memcpy (&(rsdt
->creator_id
), root_creator_id
, 6);
364 rsdt
->creator_rev
= root_creator_rev
;
366 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
367 *(rsdt_entry
++) = PTR_TO_UINT32 (cur
->addr
);
369 /* Recompute checksum. */
371 rsdt
->checksum
= 1 + ~grub_byte_checksum (rsdt
, rsdt
->length
);
374 /* Regenerate ACPIv1 RSDP */
379 rsdpv1_new
= (struct grub_acpi_rsdp_v10
*) playground_ptr
;
380 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v10
);
381 grub_memcpy (&(rsdpv1_new
->signature
), "RSD PTR ", 8);
382 grub_memcpy (&(rsdpv1_new
->oemid
), root_oemid
, sizeof (rsdpv1_new
->oemid
));
383 rsdpv1_new
->revision
= 0;
384 rsdpv1_new
->rsdt_addr
= PTR_TO_UINT32 (rsdt_addr
);
385 rsdpv1_new
->checksum
= 0;
386 rsdpv1_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv1_new
,
387 sizeof (*rsdpv1_new
));
388 grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
394 struct grub_acpi_table_header
*xsdt
;
395 struct efiemu_acpi_table
*cur
;
396 grub_uint64_t
*xsdt_entry
;
400 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
404 xsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
405 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
407 xsdt_entry
= (grub_uint64_t
*)(xsdt
+ 1);
408 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
409 *(xsdt_entry
++) = PTR_TO_UINT64 (cur
->addr
);
410 grub_memcpy (&(xsdt
->signature
), "XSDT", 4);
411 xsdt
->length
= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
413 grub_memcpy (&(xsdt
->oemid
), root_oemid
, sizeof (xsdt
->oemid
));
414 grub_memcpy (&(xsdt
->oemtable
), root_oemtable
, sizeof (xsdt
->oemtable
));
415 xsdt
->oemrev
= root_oemrev
;
416 grub_memcpy (&(xsdt
->creator_id
), root_creator_id
, sizeof (xsdt
->creator_id
));
417 xsdt
->creator_rev
= root_creator_rev
;
419 xsdt
->checksum
= 1 + ~grub_byte_checksum (xsdt
, xsdt
->length
);
422 rsdpv2_new
= (struct grub_acpi_rsdp_v20
*) playground_ptr
;
423 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v20
);
424 grub_memcpy (&(rsdpv2_new
->rsdpv1
.signature
), "RSD PTR ",
425 sizeof (rsdpv2_new
->rsdpv1
.signature
));
426 grub_memcpy (&(rsdpv2_new
->rsdpv1
.oemid
), root_oemid
,
427 sizeof (rsdpv2_new
->rsdpv1
.oemid
));
428 rsdpv2_new
->rsdpv1
.revision
= rev2
;
429 rsdpv2_new
->rsdpv1
.rsdt_addr
= PTR_TO_UINT32 (rsdt_addr
);
430 rsdpv2_new
->rsdpv1
.checksum
= 0;
431 rsdpv2_new
->rsdpv1
.checksum
= 1 + ~grub_byte_checksum
432 (&(rsdpv2_new
->rsdpv1
), sizeof (rsdpv2_new
->rsdpv1
));
433 rsdpv2_new
->length
= sizeof (*rsdpv2_new
);
434 rsdpv2_new
->xsdt_addr
= PTR_TO_UINT64 (xsdt
);
435 rsdpv2_new
->checksum
= 0;
436 rsdpv2_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv2_new
,
438 grub_dprintf ("acpi", "Generated ACPIv2 tables\n");
444 struct efiemu_acpi_table
*cur
, *t
;
446 grub_free (table_dsdt
);
447 for (cur
= acpi_tables
; cur
;)
450 grub_free (cur
->addr
);
459 grub_cmd_acpi (struct grub_extcmd
*cmd
,
460 int argc
, char **args
)
462 struct grub_arg_list
*state
= cmd
->state
;
463 struct grub_acpi_rsdp_v10
*rsdp
;
464 struct efiemu_acpi_table
*cur
, *t
;
469 /* Default values if no RSDP is found. */
474 playground
= playground_ptr
= 0;
477 rsdp
= (struct grub_acpi_rsdp_v10
*) grub_machine_acpi_get_rsdpv2 ();
480 rsdp
= grub_machine_acpi_get_rsdpv1 ();
484 grub_uint32_t
*entry_ptr
;
488 /* RSDT consists of header and an array of 32-bit pointers. */
489 struct grub_acpi_table_header
*rsdt
;
491 exclude
= state
[0].set
? grub_strdup (state
[0].arg
) : 0;
494 for (ptr
= exclude
; *ptr
; ptr
++)
495 *ptr
= grub_tolower (*ptr
);
498 load_only
= state
[1].set
? grub_strdup (state
[1].arg
) : 0;
501 for (ptr
= load_only
; *ptr
; ptr
++)
502 *ptr
= grub_tolower (*ptr
);
505 /* Set revision variables to replicate the same version as host. */
506 rev1
= ! rsdp
->revision
;
507 rev2
= rsdp
->revision
;
508 rsdt
= (struct grub_acpi_table_header
*) UINT_TO_PTR (rsdp
->rsdt_addr
);
509 /* Load host tables. */
510 for (entry_ptr
= (grub_uint32_t
*) (rsdt
+ 1);
511 entry_ptr
< (grub_uint32_t
*) (((grub_uint8_t
*) rsdt
)
516 struct efiemu_acpi_table
*table
;
517 struct grub_acpi_table_header
*curtable
518 = (struct grub_acpi_table_header
*) UINT_TO_PTR (*entry_ptr
);
520 for (i
= 0; i
< 4;i
++)
521 signature
[i
] = grub_tolower (curtable
->signature
[i
]);
523 /* If it's FADT it contains addresses of DSDT and FACS. */
524 if (grub_strcmp (signature
, "facp") == 0)
526 struct grub_acpi_table_header
*dsdt
;
527 struct grub_acpi_fadt
*fadt
= (struct grub_acpi_fadt
*) curtable
;
529 /* Set root header variables to the same values
530 as FACP by default. */
531 grub_memcpy (&root_oemid
, &(fadt
->hdr
.oemid
),
532 sizeof (root_oemid
));
533 grub_memcpy (&root_oemtable
, &(fadt
->hdr
.oemtable
),
534 sizeof (root_oemtable
));
535 root_oemrev
= fadt
->hdr
.oemrev
;
536 grub_memcpy (&root_creator_id
, &(fadt
->hdr
.creator_id
),
537 sizeof (root_creator_id
));
538 root_creator_rev
= fadt
->hdr
.creator_rev
;
540 /* Load DSDT if not excluded. */
541 dsdt
= (struct grub_acpi_table_header
*)
542 UINT_TO_PTR (fadt
->dsdt_addr
);
543 if (dsdt
&& (! exclude
|| ! grub_strword (exclude
, "dsdt"))
544 && (! load_only
|| grub_strword (load_only
, "dsdt"))
545 && dsdt
->length
>= sizeof (*dsdt
))
547 dsdt_size
= dsdt
->length
;
548 table_dsdt
= grub_malloc (dsdt
->length
);
553 grub_free (load_only
);
554 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
555 "couldn't allocate table");
557 grub_memcpy (table_dsdt
, dsdt
, dsdt
->length
);
560 /* Save FACS address. FACS shouldn't be overridden. */
561 facs_addr
= fadt
->facs_addr
;
564 /* Skip excluded tables. */
565 if (exclude
&& grub_strword (exclude
, signature
))
567 if (load_only
&& ! grub_strword (load_only
, signature
))
571 if (curtable
->length
< sizeof (*curtable
))
574 table
= (struct efiemu_acpi_table
*) grub_malloc
575 (sizeof (struct efiemu_acpi_table
));
580 grub_free (load_only
);
581 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
582 "couldn't allocate table structure");
584 table
->size
= curtable
->length
;
585 table
->addr
= grub_malloc (table
->size
);
586 playground_size
+= table
->size
;
590 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
591 "couldn't allocate table");
593 table
->next
= acpi_tables
;
595 grub_memcpy (table
->addr
, curtable
, table
->size
);
598 grub_free (load_only
);
601 /* Does user specify versions to generate? */
602 if (state
[2].set
|| state
[3].set
)
611 /* Does user override root header information? */
613 grub_strncpy (root_oemid
, state
[4].arg
, sizeof (root_oemid
));
615 grub_strncpy (root_oemtable
, state
[5].arg
, sizeof (root_oemtable
));
617 root_oemrev
= grub_strtoul (state
[6].arg
, 0, 0);
619 grub_strncpy (root_creator_id
, state
[7].arg
, sizeof (root_creator_id
));
621 root_creator_rev
= grub_strtoul (state
[8].arg
, 0, 0);
623 /* Load user tables */
624 for (i
= 0; i
< argc
; i
++)
630 file
= grub_gzfile_open (args
[i
], 1);
634 return grub_error (GRUB_ERR_BAD_OS
, "couldn't open file %s", args
[i
]);
637 size
= grub_file_size (file
);
638 if (size
< sizeof (struct grub_acpi_table_header
))
640 grub_file_close (file
);
642 return grub_error (GRUB_ERR_BAD_OS
, "file %s is too small", args
[i
]);
645 buf
= (char *) grub_malloc (size
);
648 grub_file_close (file
);
650 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
651 "couldn't read file %s", args
[i
]);
654 if (grub_file_read (file
, buf
, size
) != (int) size
)
656 grub_file_close (file
);
658 return grub_error (GRUB_ERR_BAD_OS
, "couldn't read file %s", args
[i
]);
660 grub_file_close (file
);
662 if (grub_memcmp (((struct grub_acpi_table_header
*) buf
)->signature
,
665 grub_free (table_dsdt
);
671 struct efiemu_acpi_table
*table
;
672 table
= (struct efiemu_acpi_table
*) grub_malloc
673 (sizeof (struct efiemu_acpi_table
));
677 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
678 "couldn't allocate table structure");
683 playground_size
+= table
->size
;
685 table
->next
= acpi_tables
;
691 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
695 playground_size
+= dsdt_size
;
697 playground_size
+= sizeof (struct grub_acpi_table_header
) + 4 * numoftables
;
699 playground_size
+= sizeof (struct grub_acpi_rsdp_v10
);
701 playground_size
+= sizeof (struct grub_acpi_table_header
) + 8 * numoftables
;
703 playground_size
+= sizeof (struct grub_acpi_rsdp_v20
);
705 playground
= playground_ptr
706 = grub_mmap_malign_and_register (1, playground_size
, &mmapregion
,
707 GRUB_MACHINE_MEMORY_ACPI
, 0);
712 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
713 "couldn't allocate space for ACPI tables");
716 setup_common_tables ();
718 /* Request space for RSDPv1. */
722 /* Request space for RSDPv2+ and XSDT. */
726 for (cur
= acpi_tables
; cur
;)
734 if (! state
[9].set
&& (err
= grub_acpi_create_ebda ()))
738 grub_mmap_free_and_unregister (mmapregion
);
742 #ifdef GRUB_MACHINE_EFI
744 struct grub_efi_guid acpi
= GRUB_EFI_ACPI_TABLE_GUID
;
745 struct grub_efi_guid acpi20
= GRUB_EFI_ACPI_20_TABLE_GUID
;
747 grub_efi_system_table
->boot_services
->install_configuration_table
748 (&acpi20
, grub_acpi_get_rsdpv2 ());
749 grub_efi_system_table
->boot_services
->install_configuration_table
750 (&acpi
, grub_acpi_get_rsdpv1 ());
754 return GRUB_ERR_NONE
;
757 static grub_extcmd_t cmd
;
761 cmd
= grub_register_extcmd ("acpi", grub_cmd_acpi
,
762 GRUB_COMMAND_FLAG_BOTH
,
763 N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
764 "--load-only=table1,table2] FILE1"
766 N_("Load host ACPI tables and tables "
767 "specified by arguments."),
773 grub_unregister_extcmd (cmd
);