ACPI Table基本知识


1ACPI table 在BIOS 里面用ASL code 去描述。而ACPI Table又分成不同类型的Table(RSDT/FADT/DSDT...etc).

2像是我们比较常使用的DSDT Table就是放了一些event code.简单说就是当某个H/W event发生后,系统会依照

描述在这个DSDT Table中的ASL code去执行,而这些Acpi Table 包在BIOS ROM 中的形式是AML Code (类似

机器码)。

3. BIOS在开机过程中会把包在BIOS ROM中的Acpi Table 载入到RAM中,然后留下一些信息给OS来找到他们,

最简单的例子就是RSDP Structure会放在1M以下的某个位置(一般是E0000h~FFFFh),然后OS就可以透过搜寻

Signature(某个标记字)的方式来找到其他的Acpi Table entry point。

4. OS 需要有一个AML翻译器去翻译这些AML code,然后去执行他们。

5.每个 Platform 的host controller的寄存器位置不同,所以BIOS需要透过ACPI Table来告知OS这些寄存器的

位置,这样子做的好处是OS不需要知道你是在什么Platform,因为他只单纯看BIOS所提供的HW信息。


结合ASL代码学习ACPI

1.从  _STA 说起.

_STA 描述了一个设备的当前状态,比如说它可以告诉操作系统某个device 是否存在,或者说,是否要show出来。具体参考ACPI spec 6.3.7(version 6.0)

这个object 描述了某个device 的当前状态,它可以是这三种情况:enabled, disabled 或者removed.


OSPM(其实就是OS) 在调用 INI 之前会先执行_STA 这个method.   先检测到它存在了,再去初始化它,不存在,也就没有初始化一说了。


如果某个device 下面,没有放这个_STA method ,我们默认它是存在并且正常工作的。


参数:

None


返回值:

Bit[0]   如果device 存在将会被置起

Bit[1]  如果device 被置起,并且decode 到相应的resource

Bit[2]  如果希望将其在UI中show出来,那么将这一位置起

Bit[3]  如果能正常工作,这一位会被置起。

Bit[4]  如果电池存在,置起这一位

Bit[31:5] 保留起来,以后用



    // _STA (Status)
    //
    // This object returns the current status of a device.
    //
    // Arguments: (0)
    //   None
    // Return Value:
    //   An Integer containing a device status bitmap:
    //    Bit 0 - Set if the device is present.
    //    Bit 1 - Set if the device is enabled and decoding its resources.
    //    Bit 2 - Set if the device should be shown in the UI.
    //    Bit 3 - Set if the device is functioning properly (cleared if device failed its diagnostics).
    //    Bit 4 - Set if the battery is present.
    //    Bits 5-31 - Reserved (must be cleared).
    //
    Method(_STA)
    {
      If (LEqual(DPTF,1)){
        Return(0x0F)
      } Else {
        Return(0x00)
      }
    }


动动手:一个小实验

这张图截自windows 设备管理器,他显示了系统下有哪些device.


如果你想其中某个隐藏起来,就在asl code 中找到它(比如通过hid). 然后在下面写一个_STA 方法,返回全0.

Device(RTC) // RTC
{
  Name(_HID,EISAID("PNP0B00"))

  Name(_CRS,ResourceTemplate()
  {
    IO(Decode16,0x70,0x70,0x01,0x08)
    IRQNoFlags() {8}
  })
}


加几句,写成:

Device(RTC) // RTC
{
  Name(_HID,EISAID("PNP0B00"))

  Name(_CRS,ResourceTemplate()
  {
    IO(Decode16,0x70,0x70,0x01,0x08)
    IRQNoFlags() {8}
  })
  
  Method(_STA, 0)
  {
   Return (0)
  }
}

然后,看看结果,是不是看不到RTC了?

FAQ?


谁去调用这些ASL code 中的这些method?

OS.

随便打开一份ACPI compatible (Linux , windows )的源代码,搜索_STA

ReactOS-0.3.14\drivers\bus\acpi\acpica\namespace\nsxfname.c  (取自ReactOS)

有这么几行

        /*
         * Get extra info for ACPI Device/Processor objects only:
         * Run the _STA, _ADR and, SxW, and _SxD methods.
         *
         * Note: none of these methods are required, so they may or may
         * not be present for this device. The Info->Valid bitfield is used
         * to indicate which methods were found and run successfully.
         */

        /* Execute the Device._STA method */

        Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
        if (ACPI_SUCCESS (Status))
        {
            Valid |= ACPI_VALID_STA;
        }

        /* Execute the Device._ADR method */

        Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
                    &Info->Address);
        if (ACPI_SUCCESS (Status))
        {
            Valid |= ACPI_VALID_ADR;
        }

        /* Execute the Device._SxW methods */

        Status = AcpiUtExecutePowerMethods (Node,
                    AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
                    Info->LowestDstates);
        if (ACPI_SUCCESS (Status))
        {
            Valid |= ACPI_VALID_SXWS;
        }

2. OS 如何找到ACPI table?


通过RSDP 这个signature

/*******************************************************************************
 *
 * FUNCTION:    Acpi_tb_scan_memory_for_rsdp
 *
 * PARAMETERS:  Start_address       - Starting pointer for search
 *              Length              - Maximum length to search
 *
 * RETURN:      Pointer to the RSDP if found, otherwise NULL.
 *
 * DESCRIPTION: Search a block of memory for the RSDP signature
 *
 ******************************************************************************/

u8 *
acpi_tb_scan_memory_for_rsdp (
	u8                      *start_address,
	u32                     length)
{
	u32                     offset;
	u8                      *mem_rover;


	/* Search from given start addr for the requested length  */

	for (offset = 0, mem_rover = start_address;
		 offset < length;
		 offset += RSDP_SCAN_STEP, mem_rover += RSDP_SCAN_STEP)
	{

		/* The signature and checksum must both be correct */

		if (STRNCMP ((NATIVE_CHAR *) mem_rover,
				RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 &&
			acpi_tb_checksum (mem_rover, RSDP_CHECKSUM_LENGTH) == 0)
		{
			/* If so, we have found the RSDP */

			return (mem_rover);
		}
	}

	/* Searched entire block, no RSDP was found */

	return (NULL);
}

我要小额(2元)赞助,鼓励作者写出更好的教程


如果您认为本教程质量不错,读后觉得收获很大,预期工资涨幅能超过30%,不妨小额赞助我一下,让我有动力继续写出高质量的教程。

如果你有微信,请打开微信,使用“扫一扫”付款







智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告