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__)
145 /* Context for grub_acpi_create_ebda. */
146 struct grub_acpi_create_ebda_ctx
{
148 grub_uint64_t highestlow
;
151 /* Helper for grub_acpi_create_ebda. */
153 find_hook (grub_uint64_t start
, grub_uint64_t size
, grub_memory_type_t type
,
156 struct grub_acpi_create_ebda_ctx
*ctx
= data
;
157 grub_uint64_t end
= start
+ size
;
158 if (type
!= GRUB_MEMORY_AVAILABLE
)
162 if (end
> start
+ ctx
->ebda_len
163 && ctx
->highestlow
< ((end
- ctx
->ebda_len
) & (~0xf)) )
164 ctx
->highestlow
= (end
- ctx
->ebda_len
) & (~0xf);
169 grub_acpi_create_ebda (void)
171 struct grub_acpi_create_ebda_ctx ctx
= {
176 grub_uint8_t
*ebda
, *v1inebda
= 0, *v2inebda
= 0;
177 grub_uint8_t
*targetebda
, *target
;
178 struct grub_acpi_rsdp_v10
*v1
;
179 struct grub_acpi_rsdp_v20
*v2
;
181 ebda
= (grub_uint8_t
*) (grub_addr_t
) ((*((grub_uint16_t
*)0x40e)) << 4);
183 ebda_kb_len
= *(grub_uint16_t
*) ebda
;
184 if (ebda_kb_len
> 16)
186 ctx
.ebda_len
= (ebda_kb_len
+ 1) << 10;
188 /* FIXME: use low-memory mm allocation once it's available. */
189 grub_mmap_iterate (find_hook
, &ctx
);
190 targetebda
= (grub_uint8_t
*) (grub_addr_t
) ctx
.highestlow
;
191 grub_dprintf ("acpi", "creating ebda @%llx\n",
192 (unsigned long long) ctx
.highestlow
);
193 if (! ctx
.highestlow
)
194 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
195 "couldn't find space for the new EBDA");
197 mmapregion
= grub_mmap_register ((grub_addr_t
) targetebda
, ctx
.ebda_len
,
198 GRUB_MEMORY_RESERVED
);
202 /* XXX: EBDA is unstandardized, so this implementation is heuristical. */
204 grub_memcpy (targetebda
, ebda
, 0x400);
206 grub_memset (targetebda
, 0, 0x400);
207 *((grub_uint16_t
*) targetebda
) = ebda_kb_len
+ 1;
210 v1
= grub_acpi_get_rsdpv1 ();
211 v2
= grub_acpi_get_rsdpv2 ();
212 if (v2
&& v2
->length
> 40)
215 /* First try to replace already existing rsdp. */
218 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
219 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
220 if (grub_memcmp (target
, GRUB_RSDP_SIGNATURE
, GRUB_RSDP_SIGNATURE_SIZE
) == 0
221 && grub_byte_checksum (target
,
222 sizeof (struct grub_acpi_rsdp_v10
)) == 0
223 && ((struct grub_acpi_rsdp_v10
*) target
)->revision
!= 0
224 && ((struct grub_acpi_rsdp_v20
*) target
)->length
<= v2
->length
)
226 grub_memcpy (target
, v2
, v2
->length
);
227 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
229 target
+= v2
->length
;
230 target
= (grub_uint8_t
*) ALIGN_UP((grub_addr_t
) target
, 16);
238 grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
239 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
241 if (grub_memcmp (target
, GRUB_RSDP_SIGNATURE
, GRUB_RSDP_SIGNATURE_SIZE
) == 0
242 && grub_byte_checksum (target
,
243 sizeof (struct grub_acpi_rsdp_v10
)) == 0)
245 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
246 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
248 target
+= sizeof (struct grub_acpi_rsdp_v10
);
249 target
= (grub_uint8_t
*) ALIGN_UP((grub_addr_t
) target
, 16);
255 target
= targetebda
+ 0x100;
257 /* Try contiguous zeros. */
260 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
261 for (; target
< targetebda
+ 0x400 - v2
->length
; target
+= 0x10)
262 if (iszero (target
, v2
->length
))
264 grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target
);
265 grub_memcpy (target
, v2
, v2
->length
);
267 target
+= v2
->length
;
268 target
= (grub_uint8_t
*) ALIGN_UP((grub_addr_t
) target
, 16);
276 grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
277 for (; target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
279 if (iszero (target
, sizeof (struct grub_acpi_rsdp_v10
)))
281 grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target
);
282 grub_memcpy (target
, v1
, sizeof (struct grub_acpi_rsdp_v10
));
284 target
+= sizeof (struct grub_acpi_rsdp_v10
);
285 target
= (grub_uint8_t
*) ALIGN_UP((grub_addr_t
) target
, 16);
293 grub_mmap_unregister (mmapregion
);
294 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
295 "couldn't find suitable spot in EBDA");
298 /* Remove any other RSDT. */
299 for (target
= targetebda
;
300 target
< targetebda
+ 0x400 - sizeof (struct grub_acpi_rsdp_v10
);
302 if (grub_memcmp (target
, GRUB_RSDP_SIGNATURE
, GRUB_RSDP_SIGNATURE_SIZE
) == 0
303 && grub_byte_checksum (target
,
304 sizeof (struct grub_acpi_rsdp_v10
)) == 0
305 && target
!= v1inebda
&& target
!= v2inebda
)
308 grub_dprintf ("acpi", "Switching EBDA\n");
309 (*((grub_uint16_t
*) 0x40e)) = ((grub_addr_t
) targetebda
) >> 4;
310 grub_dprintf ("acpi", "EBDA switched\n");
312 return GRUB_ERR_NONE
;
316 /* Create tables common to ACPIv1 and ACPIv2+ */
318 setup_common_tables (void)
320 struct efiemu_acpi_table
*cur
;
321 struct grub_acpi_table_header
*rsdt
;
322 grub_uint32_t
*rsdt_entry
;
326 grub_memcpy (playground_ptr
, table_dsdt
, dsdt_size
);
327 grub_free (table_dsdt
);
328 table_dsdt
= playground_ptr
;
329 playground_ptr
+= dsdt_size
;
331 /* Treat other tables. */
332 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
334 struct grub_acpi_fadt
*fadt
;
336 grub_memcpy (playground_ptr
, cur
->addr
, cur
->size
);
337 grub_free (cur
->addr
);
338 cur
->addr
= playground_ptr
;
339 playground_ptr
+= cur
->size
;
341 /* If it's FADT correct DSDT and FACS addresses. */
342 fadt
= (struct grub_acpi_fadt
*) cur
->addr
;
343 if (grub_memcmp (fadt
->hdr
.signature
, GRUB_ACPI_FADT_SIGNATURE
,
344 sizeof (fadt
->hdr
.signature
)) == 0)
346 fadt
->dsdt_addr
= (grub_addr_t
) table_dsdt
;
347 fadt
->facs_addr
= facs_addr
;
349 /* Does a revision 2 exist at all? */
350 if (fadt
->hdr
.revision
>= 3)
352 fadt
->dsdt_xaddr
= (grub_addr_t
) table_dsdt
;
353 fadt
->facs_xaddr
= facs_addr
;
356 /* Recompute checksum. */
357 fadt
->hdr
.checksum
= 0;
358 fadt
->hdr
.checksum
= 1 + ~grub_byte_checksum (fadt
, fadt
->hdr
.length
);
362 /* Fill RSDT entries. */
364 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
367 rsdt_addr
= rsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
368 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint32_t
) * numoftables
;
370 rsdt_entry
= (grub_uint32_t
*) (rsdt
+ 1);
372 /* Fill RSDT header. */
373 grub_memcpy (&(rsdt
->signature
), "RSDT", 4);
374 rsdt
->length
= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint32_t
) * numoftables
;
376 grub_memcpy (&(rsdt
->oemid
), root_oemid
, sizeof (rsdt
->oemid
));
377 grub_memcpy (&(rsdt
->oemtable
), root_oemtable
, sizeof (rsdt
->oemtable
));
378 rsdt
->oemrev
= root_oemrev
;
379 grub_memcpy (&(rsdt
->creator_id
), root_creator_id
, sizeof (rsdt
->creator_id
));
380 rsdt
->creator_rev
= root_creator_rev
;
382 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
383 *(rsdt_entry
++) = (grub_addr_t
) cur
->addr
;
385 /* Recompute checksum. */
387 rsdt
->checksum
= 1 + ~grub_byte_checksum (rsdt
, rsdt
->length
);
390 /* Regenerate ACPIv1 RSDP */
395 rsdpv1_new
= (struct grub_acpi_rsdp_v10
*) playground_ptr
;
396 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v10
);
397 grub_memcpy (&(rsdpv1_new
->signature
), GRUB_RSDP_SIGNATURE
,
398 sizeof (rsdpv1_new
->signature
));
399 grub_memcpy (&(rsdpv1_new
->oemid
), root_oemid
, sizeof (rsdpv1_new
->oemid
));
400 rsdpv1_new
->revision
= 0;
401 rsdpv1_new
->rsdt_addr
= (grub_addr_t
) rsdt_addr
;
402 rsdpv1_new
->checksum
= 0;
403 rsdpv1_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv1_new
,
404 sizeof (*rsdpv1_new
));
405 grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
411 struct grub_acpi_table_header
*xsdt
;
412 struct efiemu_acpi_table
*cur
;
413 grub_uint64_t
*xsdt_entry
;
417 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
421 xsdt
= (struct grub_acpi_table_header
*) playground_ptr
;
422 playground_ptr
+= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint64_t
) * numoftables
;
424 xsdt_entry
= (grub_uint64_t
*)(xsdt
+ 1);
425 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
426 *(xsdt_entry
++) = (grub_addr_t
) cur
->addr
;
427 grub_memcpy (&(xsdt
->signature
), "XSDT", 4);
428 xsdt
->length
= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint64_t
) * numoftables
;
430 grub_memcpy (&(xsdt
->oemid
), root_oemid
, sizeof (xsdt
->oemid
));
431 grub_memcpy (&(xsdt
->oemtable
), root_oemtable
, sizeof (xsdt
->oemtable
));
432 xsdt
->oemrev
= root_oemrev
;
433 grub_memcpy (&(xsdt
->creator_id
), root_creator_id
, sizeof (xsdt
->creator_id
));
434 xsdt
->creator_rev
= root_creator_rev
;
436 xsdt
->checksum
= 1 + ~grub_byte_checksum (xsdt
, xsdt
->length
);
439 rsdpv2_new
= (struct grub_acpi_rsdp_v20
*) playground_ptr
;
440 playground_ptr
+= sizeof (struct grub_acpi_rsdp_v20
);
441 grub_memcpy (&(rsdpv2_new
->rsdpv1
.signature
), GRUB_RSDP_SIGNATURE
,
442 sizeof (rsdpv2_new
->rsdpv1
.signature
));
443 grub_memcpy (&(rsdpv2_new
->rsdpv1
.oemid
), root_oemid
,
444 sizeof (rsdpv2_new
->rsdpv1
.oemid
));
445 rsdpv2_new
->rsdpv1
.revision
= rev2
;
446 rsdpv2_new
->rsdpv1
.rsdt_addr
= (grub_addr_t
) rsdt_addr
;
447 rsdpv2_new
->rsdpv1
.checksum
= 0;
448 rsdpv2_new
->rsdpv1
.checksum
= 1 + ~grub_byte_checksum
449 (&(rsdpv2_new
->rsdpv1
), sizeof (rsdpv2_new
->rsdpv1
));
450 rsdpv2_new
->length
= sizeof (*rsdpv2_new
);
451 rsdpv2_new
->xsdt_addr
= (grub_addr_t
) xsdt
;
452 rsdpv2_new
->checksum
= 0;
453 rsdpv2_new
->checksum
= 1 + ~grub_byte_checksum (rsdpv2_new
,
455 grub_dprintf ("acpi", "Generated ACPIv2 tables\n");
461 struct efiemu_acpi_table
*cur
, *t
;
463 grub_free (table_dsdt
);
464 for (cur
= acpi_tables
; cur
;)
467 grub_free (cur
->addr
);
476 grub_cmd_acpi (struct grub_extcmd_context
*ctxt
, int argc
, char **args
)
478 struct grub_arg_list
*state
= ctxt
->state
;
479 struct grub_acpi_rsdp_v10
*rsdp
;
480 struct efiemu_acpi_table
*cur
, *t
;
484 /* Default values if no RSDP is found. */
489 playground
= playground_ptr
= 0;
492 rsdp
= (struct grub_acpi_rsdp_v10
*) grub_machine_acpi_get_rsdpv2 ();
495 rsdp
= grub_machine_acpi_get_rsdpv1 ();
499 grub_uint32_t
*entry_ptr
;
503 /* RSDT consists of header and an array of 32-bit pointers. */
504 struct grub_acpi_table_header
*rsdt
;
506 exclude
= state
[0].set
? grub_strdup (state
[0].arg
) : 0;
509 for (ptr
= exclude
; *ptr
; ptr
++)
510 *ptr
= grub_tolower (*ptr
);
513 load_only
= state
[1].set
? grub_strdup (state
[1].arg
) : 0;
516 for (ptr
= load_only
; *ptr
; ptr
++)
517 *ptr
= grub_tolower (*ptr
);
520 /* Set revision variables to replicate the same version as host. */
521 rev1
= ! rsdp
->revision
;
522 rev2
= rsdp
->revision
;
523 rsdt
= (struct grub_acpi_table_header
*) (grub_addr_t
) rsdp
->rsdt_addr
;
524 /* Load host tables. */
525 for (entry_ptr
= (grub_uint32_t
*) (rsdt
+ 1);
526 entry_ptr
< (grub_uint32_t
*) (((grub_uint8_t
*) rsdt
)
531 struct efiemu_acpi_table
*table
;
532 struct grub_acpi_table_header
*curtable
533 = (struct grub_acpi_table_header
*) (grub_addr_t
) *entry_ptr
;
535 for (i
= 0; i
< 4;i
++)
536 signature
[i
] = grub_tolower (curtable
->signature
[i
]);
538 /* If it's FADT it contains addresses of DSDT and FACS. */
539 if (grub_strcmp (signature
, "facp") == 0)
541 struct grub_acpi_table_header
*dsdt
;
542 struct grub_acpi_fadt
*fadt
= (struct grub_acpi_fadt
*) curtable
;
544 /* Set root header variables to the same values
545 as FADT by default. */
546 grub_memcpy (&root_oemid
, &(fadt
->hdr
.oemid
),
547 sizeof (root_oemid
));
548 grub_memcpy (&root_oemtable
, &(fadt
->hdr
.oemtable
),
549 sizeof (root_oemtable
));
550 root_oemrev
= fadt
->hdr
.oemrev
;
551 grub_memcpy (&root_creator_id
, &(fadt
->hdr
.creator_id
),
552 sizeof (root_creator_id
));
553 root_creator_rev
= fadt
->hdr
.creator_rev
;
555 /* Load DSDT if not excluded. */
556 dsdt
= (struct grub_acpi_table_header
*)
557 (grub_addr_t
) fadt
->dsdt_addr
;
558 if (dsdt
&& (! exclude
|| ! grub_strword (exclude
, "dsdt"))
559 && (! load_only
|| grub_strword (load_only
, "dsdt"))
560 && dsdt
->length
>= sizeof (*dsdt
))
562 dsdt_size
= dsdt
->length
;
563 table_dsdt
= grub_malloc (dsdt
->length
);
568 grub_free (load_only
);
571 grub_memcpy (table_dsdt
, dsdt
, dsdt
->length
);
574 /* Save FACS address. FACS shouldn't be overridden. */
575 facs_addr
= fadt
->facs_addr
;
578 /* Skip excluded tables. */
579 if (exclude
&& grub_strword (exclude
, signature
))
581 if (load_only
&& ! grub_strword (load_only
, signature
))
585 if (curtable
->length
< sizeof (*curtable
))
588 table
= (struct efiemu_acpi_table
*) grub_malloc
589 (sizeof (struct efiemu_acpi_table
));
594 grub_free (load_only
);
597 table
->size
= curtable
->length
;
598 table
->addr
= grub_malloc (table
->size
);
599 playground_size
+= table
->size
;
605 table
->next
= acpi_tables
;
607 grub_memcpy (table
->addr
, curtable
, table
->size
);
610 grub_free (load_only
);
613 /* Does user specify versions to generate? */
614 if (state
[2].set
|| state
[3].set
)
623 /* Does user override root header information? */
625 grub_strncpy (root_oemid
, state
[4].arg
, sizeof (root_oemid
));
627 grub_strncpy (root_oemtable
, state
[5].arg
, sizeof (root_oemtable
));
629 root_oemrev
= grub_strtoul (state
[6].arg
, 0, 0);
631 grub_strncpy (root_creator_id
, state
[7].arg
, sizeof (root_creator_id
));
633 root_creator_rev
= grub_strtoul (state
[8].arg
, 0, 0);
635 /* Load user tables */
636 for (i
= 0; i
< argc
; i
++)
642 file
= grub_file_open (args
[i
]);
649 size
= grub_file_size (file
);
650 if (size
< sizeof (struct grub_acpi_table_header
))
652 grub_file_close (file
);
654 return grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
658 buf
= (char *) grub_malloc (size
);
661 grub_file_close (file
);
666 if (grub_file_read (file
, buf
, size
) != (int) size
)
668 grub_file_close (file
);
671 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
675 grub_file_close (file
);
677 if (grub_memcmp (((struct grub_acpi_table_header
*) buf
)->signature
,
680 grub_free (table_dsdt
);
686 struct efiemu_acpi_table
*table
;
687 table
= (struct efiemu_acpi_table
*) grub_malloc
688 (sizeof (struct efiemu_acpi_table
));
697 playground_size
+= table
->size
;
699 table
->next
= acpi_tables
;
705 for (cur
= acpi_tables
; cur
; cur
= cur
->next
)
709 playground_size
+= dsdt_size
;
711 playground_size
+= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint32_t
) * numoftables
;
713 playground_size
+= sizeof (struct grub_acpi_rsdp_v10
);
715 playground_size
+= sizeof (struct grub_acpi_table_header
) + sizeof (grub_uint64_t
) * numoftables
;
717 playground_size
+= sizeof (struct grub_acpi_rsdp_v20
);
719 playground
= playground_ptr
720 = grub_mmap_malign_and_register (1, playground_size
, &mmapregion
,
721 GRUB_MEMORY_ACPI
, 0);
726 return grub_error (GRUB_ERR_OUT_OF_MEMORY
,
727 "couldn't allocate space for ACPI tables");
730 setup_common_tables ();
732 /* Request space for RSDPv1. */
736 /* Request space for RSDPv2+ and XSDT. */
740 for (cur
= acpi_tables
; cur
;)
748 #if defined (__i386__) || defined (__x86_64__)
752 err
= grub_acpi_create_ebda ();
757 grub_mmap_free_and_unregister (mmapregion
);
763 #ifdef GRUB_MACHINE_EFI
765 struct grub_efi_guid acpi
= GRUB_EFI_ACPI_TABLE_GUID
;
766 struct grub_efi_guid acpi20
= GRUB_EFI_ACPI_20_TABLE_GUID
;
768 grub_efi_system_table
->boot_services
->install_configuration_table
769 (&acpi20
, grub_acpi_get_rsdpv2 ());
770 grub_efi_system_table
->boot_services
->install_configuration_table
771 (&acpi
, grub_acpi_get_rsdpv1 ());
775 return GRUB_ERR_NONE
;
778 static grub_extcmd_t cmd
;
782 cmd
= grub_register_extcmd ("acpi", grub_cmd_acpi
, 0,
783 N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
784 "--load-only=TABLE1,TABLE2] FILE1"
786 N_("Load host ACPI tables and tables "
787 "specified by arguments."),
793 grub_unregister_extcmd (cmd
);