_CR tracing
#define _CR(Record, TYPE, Field)
((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
typedef struct _EFI_MEMORY_POOLS_LISI{
EFI_PHYSICAL_ADDRESS Address;
UINTN PoolSize;
EFI_LIST_ENTRY Link;
} EFI_MEMORY_POOLS_LISI;
首先先講Struct
Struct 內的物件記憶體排列如下 :
ex:
Script : 0x6194C90
Address : 0x6194C90
PoolSize : 0x6194C98
Link : 0x6194C9C
再來是 _CR(Record, TYPE, Field)
使用_CR 的方式 :
EFI_MEMORY_POOLS_LISI *Script;
Script = _CR(NowLink, EFI_MEMORY_POOLS_LISI, Link);
NowLink 是 我們要取的那個結構內的Link 位址
_CR 會去計算出結構的起始位址,然後回傳回來
好,那_CR 又是怎麼做的呢??
接下來是重點
Script = _CR(NowLink, EFI_MEMORY_POOLS_LISI, Link);
#define _CR(Record, TYPE, Field)
((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
替換後如下
((EFI_MEMORY_POOLS_LISI *) ( (CHAR8 *)(NowLink) - (CHAR8 *) &(((EFI_MEMORY_POOLS_LISI *) 0)->Link)))
拆解之後 Print 的結果 :
(CHAR8 *)(NowLink) : 6194C9C
(CHAR8 *) &(((EFI_MEMORY_POOLS_LISI *) 0)->Link) : C => 注意他取出 Link 的 Offset
&(((EFI_MEMORY_POOLS_LISI *) 0)->Link) : C
((EFI_MEMORY_POOLS_LISI *) 0) : 0
所以 NowLink 的位址減掉 Offset,就會是它的結構起始點位址!!!
重點在於 &(((EFI_MEMORY_POOLS_LISI *) 0)->Link) 這個特別的用法
使用雙指標的時機
當你宣告了一個指標,然後又call一個Function 去修改這個"指標內"的內容
Entry {
EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpPtr;
...
Status = AcpiMain(&RsdpPtr);
}
EFI_STATUS
AcpiMain (
IN OUT EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER **TablePtr
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_BLACK | EFI_LIGHTGREEN );
Print (L"ACPI Utility by Harry Lin\n%N");
Status = LibGetSystemConfigurationTable (&gEfiAcpiTableGuid, TablePtr); // gEfiAcpi20TableGuid "ACPI 2.0 Table"
if (EFI_ERROR (Status)) {
...
}
原本寫法,這一種方法不行!!
RsdpPtr 內容不會被改
Entry {
EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpPtr;
...
Status = AcpiMain(RsdpPtr);
}
EFI_STATUS
AcpiMain (
IN OUT EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *TablePtr
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
ST->ConOut->SetAttribute(ST->ConOut, EFI_BACKGROUND_BLACK | EFI_LIGHTGREEN );
Print (L"ACPI Utility by Harry Lin\n%N");
Status = LibGetSystemConfigurationTable (&gEfiAcpiTableGuid, &TablePtr); // gEfiAcpi20TableGuid "ACPI 2.0 Table"
if (EFI_ERROR (Status)) {
...
}
速記法 : 要修改內容請傳址 (&Ptr)
