[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Loading DSDT table using 'acpi' or some memory write command?

From: Nando Eva
Subject: Re: Loading DSDT table using 'acpi' or some memory write command?
Date: Mon, 27 Mar 2017 14:12:40 +0000 (UTC)

OK, I found the cause if the problem:

- the ACPI tables specified to the 'acpi' command are loaded to new addresses and a new RSDT and XSDT created with pointers to them. This can be confirmed by the 'lsacpi' command.

- the RSDP isn't updated to point to the new RSDT and XSDT.

So when chainload the OS, the original RSDT and XSDT are referenced from the RSDP.

I'm now manually doing the 'acpi [DSDT]' table load, then a 'lsacpi -2' to find the new RSDT+XSDT addresses and updating the RSDP via two write_dword memory writes (though not doing checksum correction).

Can a pach be made for grub2 to correct this behaviour to be automated without such manual intervention?

Thank you,

On Tuesday, 28 February 2017, 5:21, Nando Eva <address@hidden> wrote:

Vladimir 'phcoder' Serbinenko wrote:

I reproduced the bug. I'm investigating
>> Apparently finish_boot_services rewrites acpi tables. It's possible to workaround this, possibly by using acpi table protocol. >> But it's certainely not for 2.02 at this point.

Thank you for investigating the issue. Earlier I did a test to check to see if UEFI chainloading was altering ACPI tables. I did this by:

1. performing two grub2 "write_dword" console memory commands to enable ASPM in the ACPI FADT (FACP on my system) table as per

2. then chainloaded from Grub2 to windows: chainloader /efi/Microsoft/Boot/bootmgfw.efi

The ASPM enabling change was there as found by using r-w everything and reported by 'powercfg /energy', indicating the UEFI chainloading isn't, at least for ACPI FADT (FACP), altering the in-memory table.

As the DSDT table is much larger, I can't really write_dword it. Hence asking for some other memory loading module.

As another lead, I found the mentioned finish_boot_services routine in mm.c, quoted below. Would you mind pointing out which code is rewriting the ACPI tables?

Thank you,

grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf,
                   grub_efi_uintn_t *map_key,
                   grub_efi_uintn_t *efi_desc_size,
                   grub_efi_uint32_t *efi_desc_version)
  grub_efi_boot_services_t *b;
  grub_efi_status_t status;

#if defined (__i386__) || defined (__x86_64__)
  const grub_uint16_t apple[] = { 'A', 'p', 'p', 'l', 'e' };
  int is_apple;

  is_apple = (grub_memcmp (grub_efi_system_table->firmware_vendor,
               apple, sizeof (apple)) == 0);

  while (1)
      if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
                   &finish_desc_size, &finish_desc_version) < 0)
    return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");

      if (outbuf && *outbuf_size < finish_mmap_size)
    return grub_error (GRUB_ERR_IO, "memory map buffer is too small");

      finish_mmap_buf = grub_malloc (finish_mmap_size);
      if (!finish_mmap_buf)
    return grub_errno;

      if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key,
                   &finish_desc_size, &finish_desc_version) <= 0)
      grub_free (finish_mmap_buf);
      return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");

      b = grub_efi_system_table->boot_services;
      status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle,
      if (status == GRUB_EFI_SUCCESS)

      if (status != GRUB_EFI_INVALID_PARAMETER)
      grub_free (finish_mmap_buf);
      return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services");

      grub_free (finish_mmap_buf);
      grub_printf ("Trying to terminate EFI services again\n");
  grub_efi_is_finished = 1;
  if (outbuf_size)
    *outbuf_size = finish_mmap_size;
  if (outbuf)
    grub_memcpy (outbuf, finish_mmap_buf, finish_mmap_size);
  if (map_key)
    *map_key = finish_key;
  if (efi_desc_size)
    *efi_desc_size = finish_desc_size;
  if (efi_desc_version)
    *efi_desc_version = finish_desc_version;

#if defined (__i386__) || defined (__x86_64__)
  if (is_apple)
    stop_broadcom ();

  return GRUB_ERR_NONE;


On Tuesday, 28 February 2017, 2:13, Nando Eva <address@hidden> wrote:

Andrei Borzenkov wrote:
>> That's more or less what grub tries to do. We cannot really overwrite >> ACPI tables because they may be located in read-only memory, but it >> attempts to create EBDA and place new RSDP there and update EBDA >> address as well as update RSDP pointer in EFI system table. I would >> suggest trying to load something else (like Linux) and check whether >> it sees new or old table.

This user had 'acpi' also fail to replace the FACS ACPI table on Linux:

The DSDT I require is for Win10. Win10 has a registry override method to replace a DSDT but requires test signing mode to do it, along with some app restrictions/incompatibilities.

I require a pre-boot DSDT override method to overcome Win10 test signing mode AND have my required DSDT table loaded. Just need an in-memory DSDT subsitution tool to do it.

I have been able to accomplish this using MBR boot because the tools exist. For the more popular UEFI,I have yet to find a load-file-into-memory-location tool to make it possible. Only things are the multiboot file encapsulation, hexedit and write_dword. All not the right fit.

Any chance the grub-devel team can help out here with either a load-file-to-memory-location module/tool (where I need to find the address) or specifically one that does a in-memory DSDT override by overwriting the existing table? Of course, ppl with read-only memory can't use it just like I imagine would be the case with the current 'acpi' method.

Thank you,

reply via email to

[Prev in Thread] Current Thread [Next in Thread]