Ejemplo n.º 1
0
void
grub_acpi_halt (void)
{
  struct grub_acpi_rsdp_v20 *rsdp2;
  struct grub_acpi_rsdp_v10 *rsdp1;
      struct grub_acpi_table_header *rsdt;
      grub_uint32_t *entry_ptr;

  rsdp2 = grub_acpi_get_rsdpv2 ();
  if (rsdp2)
    rsdp1 = &(rsdp2->rsdpv1);
  else
    rsdp1 = grub_acpi_get_rsdpv1 ();
  grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
  if (!rsdp1)
    return;

  rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr;
  for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
       entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
				      + rsdt->length);
       entry_ptr++)
    {
      if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0)
	{
	  grub_uint32_t port;
	  struct grub_acpi_fadt *fadt
	    = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr);
	  struct grub_acpi_table_header *dsdt
	    = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr;
	  int sleep_type = -1;

	  port = fadt->pm1a;

	  grub_dprintf ("acpi", "PM1a port=%x\n", port);

	  if (grub_memcmp (dsdt->signature, "DSDT",
			   sizeof (dsdt->signature)) != 0)
	    break;

	  sleep_type = get_sleep_type ((grub_uint8_t *) dsdt,
				       (grub_uint8_t *) dsdt + dsdt->length);

	  if (sleep_type < 0 || sleep_type >= 8)
	    break;

	  grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n",
			sleep_type, port);

	  grub_outw (GRUB_ACPI_SLP_EN
	  	     | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff);
	}
    }

  grub_millisleep (1500);

  /* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI.  */
  grub_puts_ (N_("ACPI shutdown failed"));
}
Ejemplo n.º 2
0
grub_err_t
grub_multiboot_make_mbi (grub_uint32_t *target)
{
  grub_properly_aligned_t *ptrorig;
  grub_properly_aligned_t *mbistart;
  grub_err_t err;
  grub_size_t bufsize;
  grub_relocator_chunk_t ch;

  bufsize = grub_multiboot_get_mbi_size ();

  COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);

  err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
					  0, 0xffffffff - bufsize,
					  bufsize, MULTIBOOT_TAG_ALIGN,
					  GRUB_RELOCATOR_PREFERENCE_NONE, 1);
  if (err)
    return err;

  ptrorig = get_virtual_current_address (ch);
#if defined (__i386__) || defined (__x86_64__)
  *target = get_physical_target_address (ch);
#elif defined (__mips)
  *target = get_physical_target_address (ch) | 0x80000000;
#else
#error Please complete this
#endif

  mbistart = ptrorig;
  COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t))
		       % sizeof (grub_properly_aligned_t) == 0);
  COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
		       % sizeof (grub_properly_aligned_t) == 0);
  ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);

  {
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
    tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; 
    grub_memcpy (tag->string, cmdline, cmdline_size);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
       / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
    tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); 
    grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

#ifdef GRUB_MACHINE_PCBIOS
  {
    struct grub_apm_info info;
    if (grub_apm_get_info (&info))
      {
	struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig;

	tag->type = MULTIBOOT_TAG_TYPE_APM;
	tag->size = sizeof (struct multiboot_tag_apm); 

	tag->cseg = info.cseg;
	tag->offset = info.offset;
	tag->cseg_16 = info.cseg_16;
	tag->dseg = info.dseg;
	tag->flags = info.flags;
	tag->cseg_len = info.cseg_len;
	tag->dseg_len = info.dseg_len;
	tag->cseg_16_len = info.cseg_16_len;
	tag->version = info.version;

	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }
#endif

  {
    unsigned i;
    struct module *cur;

    for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
      {
	struct multiboot_tag_module *tag
	  = (struct multiboot_tag_module *) ptrorig;
	tag->type = MULTIBOOT_TAG_TYPE_MODULE;
	tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
	tag->mod_start = cur->start;
	tag->mod_end = tag->mod_start + cur->size;
	grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }

  {
    struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
    grub_fill_multiboot_mmap (tag);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_elf_sections *tag
      = (struct multiboot_tag_elf_sections *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS;
    tag->size = sizeof (struct multiboot_tag_elf_sections)
      + elf_sec_entsize * elf_sec_num;
    grub_memcpy (tag->sections, elf_sections, elf_sec_entsize * elf_sec_num);
    tag->num = elf_sec_num;
    tag->entsize = elf_sec_entsize;
    tag->shndx = elf_sec_shstrndx;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  {
    struct multiboot_tag_basic_meminfo *tag
      = (struct multiboot_tag_basic_meminfo *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
    tag->size = sizeof (struct multiboot_tag_basic_meminfo); 

    /* Convert from bytes to kilobytes.  */
    tag->mem_lower = grub_mmap_get_lower () / 1024;
    tag->mem_upper = grub_mmap_get_upper () / 1024;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
       / sizeof (grub_properly_aligned_t);
  }

  {
    struct grub_net_network_level_interface *net;

    FOR_NET_NETWORK_LEVEL_INTERFACES(net)
      if (net->dhcp_ack)
	{
	  struct multiboot_tag_network *tag
	    = (struct multiboot_tag_network *) ptrorig;
	  tag->type = MULTIBOOT_TAG_TYPE_NETWORK;
	  tag->size = sizeof (struct multiboot_tag_network) + net->dhcp_acklen;
	  grub_memcpy (tag->dhcpack, net->dhcp_ack, net->dhcp_acklen);
	  ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	    / sizeof (grub_properly_aligned_t);
	}
  }

  if (bootdev_set)
    {
      struct multiboot_tag_bootdev *tag
	= (struct multiboot_tag_bootdev *) ptrorig;
      tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
      tag->size = sizeof (struct multiboot_tag_bootdev); 

      tag->biosdev = biosdev;
      tag->slice = slice;
      tag->part = part;
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	/ sizeof (grub_properly_aligned_t);
    }

  {
    err = retrieve_video_parameters (&ptrorig);
    if (err)
      {
	grub_print_error ();
	grub_errno = GRUB_ERR_NONE;
      }
  }

#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
  {
    struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_EFI64;
    tag->size = sizeof (*tag);
    tag->pointer = (grub_addr_t) grub_efi_system_table;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }
#endif

#if defined (GRUB_MACHINE_EFI) && defined (__i386__)
  {
    struct multiboot_tag_efi32 *tag = (struct multiboot_tag_efi32 *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_EFI32;
    tag->size = sizeof (*tag);
    tag->pointer = (grub_addr_t) grub_efi_system_table;
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }
#endif

#if GRUB_MACHINE_HAS_ACPI
  {
    struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *)
      ptrorig;
    struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 ();
    if (a)
      {
	tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
	tag->size = sizeof (*tag) + sizeof (*a);
	grub_memcpy (tag->rsdp, a, sizeof (*a));
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }

  {
    struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *)
      ptrorig;
    struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 ();
    if (a)
      {
	tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
	tag->size = sizeof (*tag) + a->length;
	grub_memcpy (tag->rsdp, a, a->length);
	ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	  / sizeof (grub_properly_aligned_t);
      }
  }
#endif

#ifdef GRUB_MACHINE_EFI
  {
    struct multiboot_tag_efi_mmap *tag = (struct multiboot_tag_efi_mmap *) ptrorig;
    grub_efi_uintn_t efi_desc_size;
    grub_efi_uint32_t efi_desc_version;

    tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
    tag->size = sizeof (*tag) + efi_mmap_size;

    if (!keep_bs)
      err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
					   &efi_desc_size, &efi_desc_version);
    else
      {
	if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap,
				     NULL,
				     &efi_desc_size, &efi_desc_version) <= 0)
	  err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
      }
    if (err)
      return err;
    tag->descr_size = efi_desc_size;
    tag->descr_vers = efi_desc_version;
    tag->size = sizeof (*tag) + efi_mmap_size;

    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  if (keep_bs)
    {
      struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
      tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
      tag->size = sizeof (struct multiboot_tag);
      ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
	/ sizeof (grub_properly_aligned_t);
    }
#endif

  {
    struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
    tag->type = MULTIBOOT_TAG_TYPE_END;
    tag->size = sizeof (struct multiboot_tag);
    ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
      / sizeof (grub_properly_aligned_t);
  }

  ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart;
  ((grub_uint32_t *) mbistart)[1] = 0;

  return GRUB_ERR_NONE;
}
Ejemplo n.º 3
0
grub_err_t
grub_acpi_create_ebda (void)
{
  struct grub_acpi_create_ebda_ctx ctx = {
    .highestlow = 0
  };
  int ebda_kb_len = 0;
  int mmapregion = 0;
  grub_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0;
  grub_uint8_t *targetebda, *target;
  struct grub_acpi_rsdp_v10 *v1;
  struct grub_acpi_rsdp_v20 *v2;

  ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
  if (ebda)
    ebda_kb_len = *(grub_uint16_t *) ebda;
  if (ebda_kb_len > 16)
    ebda_kb_len = 0;
  ctx.ebda_len = (ebda_kb_len + 1) << 10;

  /* FIXME: use low-memory mm allocation once it's available. */
  grub_mmap_iterate (find_hook, &ctx);
  targetebda = (grub_uint8_t *) (grub_addr_t) ctx.highestlow;
  grub_dprintf ("acpi", "creating ebda @%llx\n",
		(unsigned long long) ctx.highestlow);
  if (! ctx.highestlow)
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
		       "couldn't find space for the new EBDA");

  mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ctx.ebda_len,
				   GRUB_MEMORY_RESERVED);
  if (! mmapregion)
    return grub_errno;

  /* XXX: EBDA is unstandardized, so this implementation is heuristical. */
  if (ebda_kb_len)
    grub_memcpy (targetebda, ebda, 0x400);
  else
    grub_memset (targetebda, 0, 0x400);
  *((grub_uint16_t *) targetebda) = ebda_kb_len + 1;
  target = targetebda;

  v1 = grub_acpi_get_rsdpv1 ();
  v2 = grub_acpi_get_rsdpv2 ();
  if (v2 && v2->length > 40)
    v2 = 0;

  /* First try to replace already existing rsdp. */
  if (v2)
    {
      grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n");
      for (; target < targetebda + 0x400 - v2->length; target += 0x10)
	if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
	    && grub_byte_checksum (target,
				   sizeof (struct grub_acpi_rsdp_v10)) == 0
	    && ((struct grub_acpi_rsdp_v10 *) target)->revision != 0
	    && ((struct grub_acpi_rsdp_v20 *) target)->length <= v2->length)
	  {
	    grub_memcpy (target, v2, v2->length);
	    grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
	    v2inebda = target;
	    target += v2->length;
	    target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
	    v2 = 0;
	    break;
	  }
    }

  if (v1)
    {
      grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n");
      for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
	   target += 0x10)
	if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
	    && grub_byte_checksum (target,
				   sizeof (struct grub_acpi_rsdp_v10)) == 0)
	  {
	    grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
	    grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
	    v1inebda = target;
	    target += sizeof (struct grub_acpi_rsdp_v10);
	    target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
	    v1 = 0;
	    break;
	  }
    }

  target = targetebda + 0x100;

  /* Try contiguous zeros. */
  if (v2)
    {
      grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
      for (; target < targetebda + 0x400 - v2->length; target += 0x10)
	if (iszero (target, v2->length))
	  {
	    grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target);
	    grub_memcpy (target, v2, v2->length);
	    v2inebda = target;
	    target += v2->length;
	    target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
	    v2 = 0;
	    break;
	  }
    }

  if (v1)
    {
      grub_dprintf ("acpi", "Scanning EBDA for block of zeros\n");
      for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
	   target += 0x10)
	if (iszero (target, sizeof (struct grub_acpi_rsdp_v10)))
	  {
	    grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target);
	    grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10));
	    v1inebda = target;
	    target += sizeof (struct grub_acpi_rsdp_v10);
	    target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1);
	    v1 = 0;
	    break;
	  }
    }

  if (v1 || v2)
    {
      grub_mmap_unregister (mmapregion);
      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			 "couldn't find suitable spot in EBDA");
    }

  /* Remove any other RSDT. */
  for (target = targetebda;
       target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10);
       target += 0x10)
    if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0
	&& grub_byte_checksum (target,
			       sizeof (struct grub_acpi_rsdp_v10)) == 0
	&& target != v1inebda && target != v2inebda)
      *target = 0;

  grub_dprintf ("acpi", "Switching EBDA\n");
  (*((grub_uint16_t *) 0x40e)) = ((long)targetebda) >> 4;
  grub_dprintf ("acpi", "EBDA switched\n");

  return GRUB_ERR_NONE;
}
#endif

/* Create tables common to ACPIv1 and ACPIv2+ */
static void
setup_common_tables (void)
{
  struct efiemu_acpi_table *cur;
  struct grub_acpi_table_header *rsdt;
  grub_uint32_t *rsdt_entry;
  int numoftables;

  /* Treat DSDT. */
  grub_memcpy (playground_ptr, table_dsdt, dsdt_size);
  grub_free (table_dsdt);
  table_dsdt = playground_ptr;
  playground_ptr += dsdt_size;

  /* Treat other tables. */
  for (cur = acpi_tables; cur; cur = cur->next)
    {
      struct grub_acpi_fadt *fadt;

      grub_memcpy (playground_ptr, cur->addr, cur->size);
      grub_free (cur->addr);
      cur->addr = playground_ptr;
      playground_ptr += cur->size;

      /* If it's FADT correct DSDT and FACS addresses. */
      fadt = (struct grub_acpi_fadt *) cur->addr;
      if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
		       sizeof (fadt->hdr.signature)) == 0)
	{
	  fadt->dsdt_addr = (grub_addr_t) table_dsdt;
	  fadt->facs_addr = facs_addr;

	  /* Does a revision 2 exist at all? */
	  if (fadt->hdr.revision >= 3)
	    {
	      fadt->dsdt_xaddr = (grub_addr_t) table_dsdt;
	      fadt->facs_xaddr = facs_addr;
	    }

	  /* Recompute checksum. */
	  fadt->hdr.checksum = 0;
	  fadt->hdr.checksum = 1 + ~grub_byte_checksum (fadt, fadt->hdr.length);
	}
    }

  /* Fill RSDT entries. */
  numoftables = 0;
  for (cur = acpi_tables; cur; cur = cur->next)
    numoftables++;

  rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr;
  playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables;

  rsdt_entry = (grub_uint32_t *) (rsdt + 1);

  /* Fill RSDT header. */
  grub_memcpy (&(rsdt->signature), "RSDT", 4);
  rsdt->length = sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables;
  rsdt->revision = 1;
  grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid));
  grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable));
  rsdt->oemrev = root_oemrev;
  grub_memcpy (&(rsdt->creator_id), root_creator_id, sizeof (rsdt->creator_id));
  rsdt->creator_rev = root_creator_rev;

  for (cur = acpi_tables; cur; cur = cur->next)
    *(rsdt_entry++) = (grub_addr_t) cur->addr;

  /* Recompute checksum. */
  rsdt->checksum = 0;
  rsdt->checksum = 1 + ~grub_byte_checksum (rsdt, rsdt->length);
}

/* Regenerate ACPIv1 RSDP */
static void
setv1table (void)
{
  /* Create RSDP. */
  rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr;
  playground_ptr += sizeof (struct grub_acpi_rsdp_v10);
  grub_memcpy (&(rsdpv1_new->signature), GRUB_RSDP_SIGNATURE,
	       sizeof (rsdpv1_new->signature));
  grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof  (rsdpv1_new->oemid));
  rsdpv1_new->revision = 0;
  rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr;
  rsdpv1_new->checksum = 0;
  rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
						  sizeof (*rsdpv1_new));
  grub_dprintf ("acpi", "Generated ACPIv1 tables\n");
}
Ejemplo n.º 4
0
void
grub_acpi_halt (void)
{
  struct grub_acpi_rsdp_v20 *rsdp2;
  struct grub_acpi_rsdp_v10 *rsdp1;
  struct grub_acpi_table_header *rsdt;
  grub_uint32_t *entry_ptr;
  grub_uint32_t port = 0;
  int sleep_type = -1;

  rsdp2 = grub_acpi_get_rsdpv2 ();
  if (rsdp2)
    rsdp1 = &(rsdp2->rsdpv1);
  else
    rsdp1 = grub_acpi_get_rsdpv1 ();
  grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
  if (!rsdp1)
    return;

  rsdt = (struct grub_acpi_table_header *)
    io_map_cached (rsdp1->rsdt_addr, sizeof *rsdt);
  rsdt = (struct grub_acpi_table_header *)
    io_map_cached (rsdp1->rsdt_addr, rsdt->length);

  for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
       entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
				      + rsdt->length);
       entry_ptr++)
    {
      if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4),
		       "FACP", 4) == 0)
	{
	  struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *)
	    io_map_cached (*entry_ptr, sizeof *fadt);

	  struct grub_acpi_table_header *dsdt =
	    (struct grub_acpi_table_header *)
	    io_map_cached (fadt->dsdt_addr, sizeof *dsdt);
	  grub_uint8_t *buf = (grub_uint8_t *)
	    io_map_cached (fadt->dsdt_addr, dsdt->length);

	  port = fadt->pm1a;

	  grub_dprintf ("acpi", "PM1a port=%x\n", port);

	  if (grub_memcmp (dsdt->signature, "DSDT",
			   sizeof (dsdt->signature)) == 0
	      && sleep_type < 0)
	    sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length,
					 NULL, 0);
	}
      else
	if (grub_memcmp ((void *) io_map_cached (*entry_ptr, 4), "SSDT", 4) == 0
	    && sleep_type < 0)
	{
	  struct grub_acpi_table_header *ssdt
	    = (struct grub_acpi_table_header *) (grub_addr_t)
	    io_map_cached (*entry_ptr, sizeof *ssdt);
	  grub_uint8_t *buf = (grub_uint8_t *)
	    io_map_cached (*entry_ptr, ssdt->length);

	  grub_dprintf ("acpi", "SSDT = %p\n", ssdt);

	  sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0);
	}
    }

  grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port);
  if (port && sleep_type >= 0 && sleep_type < 8)
    grub_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET),
	       port & 0xffff);

  grub_millisleep (1500);

  /* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI.  */
  grub_puts_ (N_("ACPI shutdown failed"));
}