先了解一下OSPM, _PTS, _WAK之間的flow。
Transitioning from the Working to the Sleeping State
- OSPM決定要進入sleeping state(S1, S2, S3, S4),這邊可以是你自己按的也可以是一些電源選項達成。
- OSPM會去call ACPI裡面的_TTS(Transition to State)看是要進到哪個sleeping state。
- 接著OSPM會去call device的_PRW(Power Resources to Wake)去確認有哪些device可以叫醒系統。
- OSPM要把所有device放進相對的sleeping state,可以wake的device就進到Dx state,反之進D3。
- OSPM call _PTS(Prepare to Sleep),_PTS在做什麼根據platform不同就會有所差異,主要就是傳遞現在要進哪個state,有些platform會在這邊把wake的enable起來還有把status清乾淨。
- OSPM會把其他processor的data存進memory。
- OSPM把waking vector放進FACS table裡。
- Clear WAK_STS in PM1a_STS(bit15),準備之後可以正常wake。
- 這時候才把local processor的data存進memory裡,如果是S1, S2, S3的話就會把caches清掉。
- OSPM會把GPE 或是其他可以wake的中斷enable起來。
- 如果是S4的話,OSPM會把S4BIOS_REQ寫進SMI_CMD port。
- 不是的話,OSPM會去填PM1a_CNT裡面的SLP_TYPx和SLP_EN。
- SLP_EN設起來以後就是HW的事情了。
Transitioning from the Working to the Soft Off State
- OSPM call _PTS傳遞即將進入S5。
- OSPM把所有的device關掉
- OSPM填SLP_TYP和SLP_EN設起來就進S5了。
接下來是wake起來後的flow
上面兩張圖是wake起來以後走的路線,現在總算知道S3起來以後會走到Waking Vector,Waking Vector是什麼呢?
Waking Vector是在系統要睡下去的時候,OSPM會寫進FACS(Firmware ACPI Control Structure)裡面的Byte Offset=12的位置。
--------------------------------------------------------------------------------------------------------------------
Field | Byte Length | Byte Offset | Description
--------------------------------------------------------------------------------------------------------------------
Firmware | 4 | 12 | Before transitioning the system into a global sleeping
Waking | | | state, OSPM fills this field with the physical memory
Vector | | | address of an OS-specific wake function. If this is
| | | non-zero, transfers control to the specified address.
---------------------------------------------------------------------------------------------------------------------
從code來看的話,當POST跑到最後一個PEIM也就是DxeLoadCore的時候
/**
Main entry point to last PEIM.
This function finds DXE Core in the firmware volume and transfer the control to
DXE core.
**/
EFI_STATUS
EFIAPI
DxeLoadCore (
IN CONST EFI_DXE_IPL_PPI *This,
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_HOB_POINTERS HobList
)
這裡面會去看BootMode是不是S3, Recovery Mode, Capsule Update,如果是S3的話就走S3的路,
最後會走到
//
// IA32 protected mode waking vector (Page disabled)
//
DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
SwitchStack (
(SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
NULL,
NULL,
(VOID *)(UINTN)TempStackTop
);
這個SwitchStack的功能就是轉交控制權。
回到OS以後才要call _WAK(System Wake),其實就是做跟_PTS相反的事情,然後還要把剛剛睡下去的device叫醒,
Case (43) { // interrupt 43
Store(One, ISTS) // clear interrupt status register at device X
// which is mapped via an operation region
Notify (\_SB.DEVX, 0x2) // wake event
}
Notify的第一個param是device,第二個是要notify什麼,這邊0x2是Device Wake.
Device Wake : Used to notify that the device has signaled its wake event,and that OSPM needs to notify OSPM native device for the device.
This is only used for devices that support _PRW.
Notify完了以後,OS應該就會去把device和driver串起來了。