_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)