源码摘自grub2。
acpi的rsdp保存在bios扩展数据区域或地址0xe0000~0xfffff区域内,通过搜索这两个地址区域找到rsdp。
struct acpi_rsdp_v10 *
machine_acpi_get_rsdpv1 (void){
int ebda_len;
uint8_t *ebda, *ptr;
printf ("acpi:Looking for RSDP. Scanning EBDA\n");
ebda = (uint8_t *) ((* ((uint16_t *) 0x40e)) << 4);
ebda_len = * (uint16_t *) ebda;
if (! ebda_len)
return 0;
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
if (memcmp (ptr, "RSD PTR ", 8) == 0
&& byte_checksum (ptr, sizeof (struct acpi_rsdp_v10)) == 0
&& ((struct acpi_rsdp_v10 *) ptr)->revision == 0)
return (struct acpi_rsdp_v10 *) ptr;
printf ("acpi:Looking for RSDP. Scanning BIOS\n");
for (ptr = (uint8_t *) 0xe0000; ptr < (uint8_t *) 0x100000;
ptr += 16)
if (memcmp (ptr, "RSD PTR ", 8) == 0
&& byte_checksum (ptr, sizeof (struct acpi_rsdp_v10)) == 0
&& ((struct acpi_rsdp_v10 *) ptr)->revision == 0)
return (struct acpi_rsdp_v10 *) ptr;
return 0;
}
struct acpi_rsdp_v20 *
machine_acpi_get_rsdpv2 (void)
{
int ebda_len;
uint8_t *ebda, *ptr;
printf ("acpi:Looking for RSDP. Scanning EBDA\n");
ebda = (uint8_t *) ((* ((uint16_t *) 0x40e)) << 4);
ebda_len = * (uint16_t *) ebda;
if (! ebda_len)
return 0;
for (ptr = ebda; ptr < ebda + 0x400; ptr += 16)
if (memcmp (ptr, "RSD PTR ", 8) == 0
&& byte_checksum (ptr, sizeof (struct acpi_rsdp_v10)) == 0
&& ((struct acpi_rsdp_v10 *) ptr)->revision != 0
&& ((struct acpi_rsdp_v20 *) ptr)->length < 1024
&& byte_checksum (ptr, ((struct acpi_rsdp_v20 *) ptr)->length)
== 0)
return (struct acpi_rsdp_v20 *) ptr;
printf ("acpi:Looking for RSDP. Scanning BIOS\n");
for (ptr = (uint8_t *) 0xe0000; ptr < (uint8_t *) 0x100000;
ptr += 16)
if (memcmp (ptr, "RSD PTR ", 8) == 0
&& byte_checksum (ptr, sizeof (struct acpi_rsdp_v10)) == 0
&& ((struct acpi_rsdp_v10 *) ptr)->revision != 0
&& ((struct acpi_rsdp_v20 *) ptr)->length < 1024
&& byte_checksum (ptr, ((struct acpi_rsdp_v20 *) ptr)->length)
== 0)
return (struct acpi_rsdp_v20 *) ptr;
return 0;
}