小華的部落格

搜尋此網誌

網頁

星期日, 5月 25, 2025

Dump TCG log

Dump TCG log

    一個簡易的方式在UEFI Shell底下,先找到TPM2 的ACPI Table ,再從Table中找到紀錄TCG log的記憶體位址(一般UEFI PCD目前都是設定0x10000 大小,但進入OS後,OS有可能會加大這塊的內容) ,然後分析TCG log中的每一筆紀錄的Event , 然後重新計算Digest ,這樣子可以呈現出BIOS交給OS前,TCG log中所記錄的TPM PCR可能的值會是甚麼. 底下是部分實作的程式碼,幫助大家了解流程. 


        // Loop through all ACPI tables to find TPM2

        Status = GetAcpiTableBySignature(SIGNATURE_32('T','P','M','2'), &Table);

        Tpm2Table =  (EFI_TPM2_ACPI_TABLE_V4 *) Table;


        if (Tpm2Table == NULL) {

            Print(L"[Fail] TPM2 ACPI Table not found\n");

            return EFI_NOT_FOUND;

        }


        Print(L"TPM2 ACPI Table found\n");

        Print(L"Event Log Start Address: 0x%lx\n", Tpm2Table->Lasa);

        Print(L"Event Log Length: %u bytes\n", Tpm2Table->Laml);

        Print(L"******** TCG Log Dump ******** \n");

        PrintHexAndAscii((UINT8 *) Tpm2Table->Lasa, (UINTN) Tpm2Table->Laml); // Print partial event data  


        Print(L"******** TCG Events ******** \n");


        // 儲存 PCR0 到 PCR23 的最後 Digest

        PCRDigest PcrDigests[PCR_COUNT];

        ZeroMem(PcrDigests, sizeof(PCRDigest) * PCR_COUNT);


        MY_ACPI_TCG2_EVENT *TcgEvent = (MY_ACPI_TCG2_EVENT *)(UINTN)Tpm2Table->Lasa;

        UINT8 *LogEnd = (UINT8 *)(UINTN)(Tpm2Table->Lasa + Tpm2Table->Laml);

        UINTN EventIndex = 0;


        while ((UINT8 *)TcgEvent < LogEnd) {

            UINT8 *EventStart = (UINT8 *)TcgEvent;

               //TODO:  1. 處理EV_NO_ACTION

                               2.CalculateDigest (CombinedData, CombinedDataSize, PcrDigests[PcrIndex].Digest, AlgId);


       } 

...

// 1.找到事件起始位置。
// 2.依序讀出:
// PCRIndex(4 bytes)
// EventType(4 bytes)
// DigestCount(4 bytes)
// 3.每個 Digest 結構:
//        AlgorithmId(2 bytes)
//        Digest(對 SHA128 而言,是 20 bytes, SHA256 而言,是 32 bytes..etc)
// 3.接著是 EventDataSize(4 bytes)
// 4.再來是 EventData
#pragma pack(1)
typedef struct {
    UINT32 PCRIndex;          // 4 bytes
    UINT32 EventType;         // 4 bytes
    UINT32 DigestCount;       // 4 bytes
                              // 之後是 DigestList 和 EventData
    UINT8  Event[];           // 可變長度,儲存 Digest 和 EventData (參考前面說明)
} MY_ACPI_TCG2_EVENT;
#pragma pack()

#define PCR_COUNT 24 // PCR0 到 PCR23,共 24 個 PCR

// 儲存每個 PCR 的最後一筆 Digest
typedef struct {
    UINT8 Digest[64];  // 假設 Digest 最長為 64 字節 (可以根據實際需要調整)
    UINTN DigestSize;  // Digest 大小
} PCRDigest;


UINTN
GetHashSizeFromAlgo(
  IN TPMI_ALG_HASH HashAlgo
  )
{
  switch (HashAlgo) {
    case TPM_ALG_SHA1:   return 20;
    case TPM_ALG_SHA256: return 32;
    case TPM_ALG_SHA384: return 48;
    case TPM_ALG_SHA512: return 64;
    case TPM_ALG_SM3_256:return 32;
    default:             return 0;
  }
}

// Hex + ASCII Dump
VOID
PrintHexAndAscii(IN UINT8 *Data, IN UINTN Length)
{
    for (UINTN i = 0; i < Length; i += 16) {
        Print(L"%08x: ", i);

        // Print hex
        for (UINTN j = 0; j < 16; j++) {
            if ((i + j) < Length) {
                Print(L"%02x ", Data[i + j]);
            } else {
                Print(L"   ");
            }
        }

        Print(L" ");

        // Print ASCII
        for (UINTN j = 0; j < 16; j++) {
            if ((i + j) < Length) {
                CHAR8 c = (CHAR8)Data[i + j];
                if (c >= 0x20 && c <= 0x7E) {
                    Print(L"%c", c);
                } else {
                    Print(L".");
                }
            }
        }

        Print(L"\n");
    }
}

// Covert to EventType string

CONST CHAR16* GetEventTypeString(UINT32 EventType)
{
    // Standard event types
    switch (EventType) {
        case EV_PREBOOT_CERT:             return L"EV_PREBOOT_CERT(0x00000000)";
        case EV_POST_CODE:                return L"EV_POST_CODE(0x00000001)";
        case EV_NO_ACTION:                return L"EV_NO_ACTION(0x00000003)";
        case EV_SEPARATOR:                return L"EV_SEPARATOR(0x00000004)";
        case EV_ACTION:                   return L"EV_ACTION(0x00000005)";
        case EV_EVENT_TAG:                return L"EV_EVENT_TAG(0x00000006)";
        case EV_S_CRTM_CONTENTS:          return L"EV_S_CRTM_CONTENTS(0x00000007)";
        case EV_S_CRTM_VERSION:           return L"EV_S_CRTM_VERSION(0x00000008)";
        case EV_CPU_MICROCODE:            return L"EV_CPU_MICROCODE(0x00000009)";
        case EV_PLATFORM_CONFIG_FLAGS:    return L"EV_PLATFORM_CONFIG_FLAGS(0x0000000A)";
        case EV_TABLE_OF_DEVICES:         return L"EV_TABLE_OF_DEVICES(0x0000000B)";
        case EV_COMPACT_HASH:             return L"EV_COMPACT_HASH(0x0000000C)";
        case EV_NONHOST_CODE:             return L"EV_NONHOST_CODE(0x0000000F)";
        case EV_NONHOST_CONFIG:           return L"EV_NONHOST_CONFIG(0x00000010)";
        case EV_NONHOST_INFO:             return L"EV_NONHOST_INFO(0x00000011)";
        case EV_OMIT_BOOT_DEVICE_EVENTS:  return L"EV_OMIT_BOOT_DEVICE_EVENTS(0x00000012)";

        // EFI specific event types (0x80000000 and above)
        case EV_EFI_VARIABLE_DRIVER_CONFIG:     return L"EV_EFI_VARIABLE_DRIVER_CONFIG(0x80000001)";
        case EV_EFI_VARIABLE_BOOT:              return L"EV_EFI_VARIABLE_BOOT(0x80000002)";
        case EV_EFI_BOOT_SERVICES_APPLICATION:  return L"EV_EFI_BOOT_SERVICES_APPLICATION(0x80000003)";
        case EV_EFI_BOOT_SERVICES_DRIVER:       return L"EV_EFI_BOOT_SERVICES_DRIVER(0x80000004)";
        case EV_EFI_RUNTIME_SERVICES_DRIVER:    return L"EV_EFI_RUNTIME_SERVICES_DRIVER(0x80000005)";
        case EV_EFI_GPT_EVENT:                  return L"EV_EFI_GPT_EVENT(0x80000006)";
        case EV_EFI_ACTION:                     return L"EV_EFI_ACTION(0x80000007)";
        case EV_EFI_PLATFORM_FIRMWARE_BLOB:     return L"EV_EFI_PLATFORM_FIRMWARE_BLOB(0x80000008)";
        case EV_EFI_HANDOFF_TABLES:             return L"EV_EFI_HANDOFF_TABLES(0x80000009)";
        case EV_EFI_PLATFORM_FIRMWARE_BLOB2:    return L"EV_EFI_PLATFORM_FIRMWARE_BLOB2(0x8000000A)";
        case EV_EFI_HANDOFF_TABLES2:            return L"EV_EFI_HANDOFF_TABLES2(0x8000000B)";
        case EV_EFI_HCRTM_EVENT:                return L"EV_EFI_HCRTM_EVENT(0x80000010)";
        case EV_EFI_VARIABLE_AUTHORITY:         return L"EV_EFI_VARIABLE_AUTHORITY(0x800000E0)";
        case EV_EFI_SPDM_FIRMWARE_BLOB:         return L"EV_EFI_SPDM_FIRMWARE_BLOB(0x800000E1)";
        case EV_EFI_SPDM_FIRMWARE_CONFIG:       return L"EV_EFI_SPDM_FIRMWARE_CONFIG(0x800000E2)";
        
        // Add 
        //case EV_EFI_SPDM_DEVICE_BLOB:           return L"EV_EFI_SPDM_DEVICE_BLOB(0x800000E1)"; // 和 EV_EFI_SPDM_FIRMWARE_BLOB 相同
        //case EV_EFI_SPDM_DEVICE_CONFIG:         return L"EV_EFI_SPDM_DEVICE_CONFIG(0x800000E2)"; // 和 EV_EFI_SPDM_FIRMWARE_CONFIG 相同

        default:                                return L"UNKNOWN(0x%08x)"; // Unknown event type
    }
}


#pragma pack(1)
typedef struct {                             // Refer to Tcg2Acpi.c 
  EFI_ACPI_DESCRIPTION_HEADER    Header;     // "TPM2"
  // Flags field is replaced in version 4 and above
  //    BIT0~15:  PlatformClass      This field is only valid for version 4 and above
  //    BIT16~31: Reserved
  UINT32                         Flags;
  UINT64                         AddressOfControlArea;
  UINT32                         StartMethod;
  UINT8                          PlatformSpecificParameters[12]; // size up to 12
  UINT32                         Laml;                           // Optional
  UINT64                         Lasa;                           // Optional
} EFI_TPM2_ACPI_TABLE_V4;
#pragma pack()


// Signature macro
//#define SIGNATURE_32(A,B,C,D)  ((UINT32)(A) | ((UINT32)(B)<<8) | ((UINT32)(C)<<16) | ((UINT32)(D)<<24))

EFI_STATUS
GetAcpiTableBySignature (
  IN  UINT32 Signature,
  OUT EFI_ACPI_DESCRIPTION_HEADER **OutTable
  )
{
  EFI_CONFIGURATION_TABLE             *ConfigTable = gST->ConfigurationTable;
  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp = NULL;
  EFI_ACPI_DESCRIPTION_HEADER         *Xsdt;
  UINT64                              *EntryPtr;
  UINTN                               EntryCount;

  // Step 1: Find RSDP
  for (UINTN i = 0; i < gST->NumberOfTableEntries; i++) {
    if (CompareGuid(&ConfigTable[i].VendorGuid, &gEfiAcpi20TableGuid)) {
      Rsdp = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)ConfigTable[i].VendorTable;
      break;
    }
  }
  if (Rsdp == NULL) {
    Print(L"[Error] ACPI 2.0 RSDP not found\n");
    return EFI_NOT_FOUND;
  }

  // Step 2: Get XSDT
  Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);
  if (Xsdt->Signature != EFI_ACPI_6_3_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
    Print(L"[Error] XSDT Signature mismatch (found: %08X)\n", Xsdt->Signature);
    return EFI_NOT_FOUND;
  }

  // Step 3: Traverse XSDT entries
  EntryCount = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);
  EntryPtr = (UINT64 *)(Xsdt + 1); // entries come right after the header

  for (UINTN i = 0; i < EntryCount; i++) {
    EFI_ACPI_DESCRIPTION_HEADER *Hdr = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)EntryPtr[i];
    if (Hdr->Signature == Signature) {
      *OutTable = Hdr;
      return EFI_SUCCESS;
    }
  }

  return EFI_NOT_FOUND;
}

EFI_STATUS
EFIAPI
CalculateDigest (
  IN UINT8  *Data,
  IN UINTN  DataSize,
  OUT UINT8  *Digest,
  IN UINT16  AlgId
  )
{
    BOOLEAN  Status;

    if (AlgId == TPM_ALG_SHA256) {
        Status = Sha256HashAll (Data, DataSize, Digest);
    } else {
        // 支援其他演算法
        return EFI_UNSUPPORTED;
    }

    if (!Status) {
        return EFI_DEVICE_ERROR;
    }

    return EFI_SUCCESS;
}

星期二, 1月 21, 2025

祝大家蛇年新年快樂

 Penny 說我很久沒更新了,所以來更新一下~

星期四, 2月 13, 2020

Git Tag



1.搜尋遠端上面的特定字串的Tag:

C:\> git ls-remote --tags origin "00.02.04"
7dd870355e439cfb8a818b6cd31f3c77f2ce40dc        refs/tags/BiosRelease/project1/00.02.04
88138555a49907d6935fe55a8261e226668ba770        refs/tags/BiosRelease/MockingbirdCmlH/00.02.04
a98bce225711b983d729fcdb25542c6e8fdebac8        refs/tags/BiosRelease/project2/00.02.04
3cd9b00479436f67fef2e44955571218e80b6046        refs/tags/BiosRelease/project3/00.02.04
c1286cb71e39bf869ae0d70208479c3683dd0989        refs/tags/BiosRelease/project4/00.02.04


2.列出遠端上的全部Tag
C:\> git ls-remote --tags origin


星期三, 6月 12, 2019

GIT 小幫手

1.如何知道某個CommitID是來自於哪個分支
       git branch -a --contains 68b6100


<會繼續補充>

星期三, 2月 20, 2019

紀錄一下好用的Git Alias



紀錄一下好用的Git Alias
C:\Users\<UserName>\.gitconfig

[alias]
lg1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all

lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all

lg = !"git lg1"

cc=!git clean -ffd && git submodule foreach --recursive git clean -fd && git reset --hard && git submodule foreach --recursive git reset --hard && git submodule update --init --recursive && git remote prune origin && git remote update --prune

ccall=!git clean -ffdx && git submodule foreach --recursive git clean -xfd && git reset --hard && git submodule foreach --recursive git reset --hard && git submodule update --init --recursive && git remote prune origin && git remote update --prune
st=!git status


pp=!git pull && git clean -ffd && git submodule foreach --recursive git clean -fd && git reset --hard && git submodule foreach --recursive git reset --hard && git submodule update --init --recursive && git remote prune origin && git remote update --prune


[git version  2.22.0 and above]

cc=!git clean -ffd && git submodule foreach --recursive 'git clean -fd' && git reset --hard && git submodule foreach --recursive 'git reset --hard' && git submodule update --init --recursive && git remote prune origin && git remote update --prune

ccall=!git clean -ffdx && git submodule foreach --recursive 'git clean -xfd' && git reset --hard && git submodule foreach --recursive 'git reset --hard' && git submodule update --init --recursive && git remote prune origin && git remote update --prune
st=!git status

pp=!git pull && git clean -ffd && git submodule foreach --recursive 'git clean -fd' && git reset --hard && git submodule foreach --recursive 'git reset --hard' && git submodule update --init --recursive && git remote prune origin && git remote update --prune


-----------------------------------
Git Pull常遇到的問題 : error: cannot lock ref ‘xxx’: ref xxx is at

git gc --prune=now
git update-ref -d refs/remotes/origin/ccc/xxx/yyy
git remote update --prune

---------------------------------
搜尋Tag

git tag -l '*Loki*'


星期一, 2月 05, 2018

UEFI Shell Utility - pwrtest.efi

The pwrtest.efi is an UEFI Shell tool that help developer to confirm RTC wake function from a system(Support on both Intel and AMD platform).

最近在幫忙ODM看一個RTC Wake 問題,所以就順便寫了一個TOOL來驗證一些東西。原本遇到的問題也解決了,所以就順便把這個小TOOL分享一下給有需要的人使用。

Usage:
    pwrtest -s3 -t 10 -w 60  ; 系統會在10 sec delay 後進入S3,然後在60 sec 後喚醒(Wake up) 
    pwrtest [-h|-s3|-s4|-s5|-s|-ss|-sx|-cb|-r]
                  -h help
                  -s3|-s4|-s5        ;選擇系統的Sx State (Intel platform)
                  -cb                   ;做coldboot ,我是透過 gRT->ResetSystem()  方式去做的
                  -ss                   ; 做Shutdown,我是透過 gRT->ResetSystem()  方式去做的
                  -sx value         ; 支援AMD platform去做Sx State,因為填的SLP_TYP值不同.
                                            value = 3/4/5 for AMD platform(S3/S4/S5)
                                            value = 5/6/7 for Intel Platform (S3/S4/S5)
e.g,
    pwrtest -sx 4 -t 5 -w 30 ; For AMD Platform,  Put system to S4 after 5 sec, then wake after 30 sec.
    pwrtest -sx 6 -t 5 -w 30 ; For INTEL Platform,  Put system to S4 after 5 sec, then wake after 30 sec.
    pwrtest -s3 -t 5 -w 30    ; For INTEL Platform,  Put system to S3 after 5 sec, then wake after 30 sec.
    pwrtest -r                       ; Warm boot
    pwrtest -cb                    ; Cold boot

[註]
    - S3 功能只能喚醒系統,喚醒後會當機,因為我沒有支援Reset Vector(Not support)
    - 有些系統S4/S5 並不支援RTC wake up,所以請跟你們的BIOS/EC確認,因為這個工具只是去填RTC Enable bit & RTC Alarm interrupt而已。


Download (Password: harrison):

version 1.1 : pwrtest



星期一, 1月 15, 2018

紀錄一下WinDbg裡面比較常用到的指令集

AMLI裡面比較常用到的指令集

AMLI(? for help)-> ?
?

Help                     - ? [<Cmd>]
Clear Breakpoints        - bc <bp list> | *
Disable Breakpoints      - bd <bp list> | *
Enable Breakpoints       - be <bp list> | *
List Breakpoints         - bl
Set Breakpoints          - bp <MethodName> | <CodeAddr> ...
Clear Event Log          - cl
Dump Event Log           - dl
Dump Object Count Table  - dc
Dump Heap                - dh [<Addr>]
Dump Stack               - ds [/v] [<Addr>]
Dump Name Space Object   - dns [[/s] [<NameStr> | <Addr>]]
Dump Data Object         - do <Addr>
Find NameSpace Object    - find <NameSeg>
Continue Execution       - g
Read Byte from Port      - i <Port>
Read Word from Port      - iw <Port>
Read DWord from Port     - id <Port>
List All Contexts        - lc
Display Nearest Method   - ln [<MethodName> | <CodeAddr>]
Notify NameSpace Object  - notify <Obj> <Value>
Write Byte to Port       - o <Port> <Byte>
Write Word to Port       - ow <Port> <Word>
Write DWord to Port      - od <Port> <DWord>
Step Over AML Code       - p
Quit to Kernel Debugger  - q
Display Context Info.    - r <Context>
Run Method               - run <MethodName> | <CodeAddr> [<ArgList>]
Set Debugger Options     - set [traceon | traceoff] [nesttraceon | nesttraceoff] [spewon | spewoff]
                               [dbgbrkon | dbgbrkoff] [lbrkon | lbrkoff] [errbrkon | errbrkoff] 
                               [verboseon | verboseoff] [logon | logoff] [logmuton | logmutoff] 
Trace Into AML Code      - t
Interpreter Trace Mode   - trace [trigon] [trigoff] [level=<n>]
                                 [add=<TrigPtStr] [zap=<TrigPtList>]
Unassemble AML code      - u [<MethodName> | <CodeAddr>]


AMLI(? for help)-> 

ACPI 裡面比較常用到的指令集
!acpicache displays all of the ACPI tables cached by the hardware application layer (HAL)

!acpiinf displays information on the configuration of the ACPI

!acpiirqarb displays the contents of the ACPI IRQ arbiter structure

!facs displays a Firmware ACPI Control Structure

!fadt displays a Fixed ACPI Description Table

!mapic displays an ACPI Multiple APIC Table

!nsobj displays an ACPI namespace object

!nstree displays a section of the ACPI namespace tree


!rsdt displays the ACPI Root System Description Table

!acpikd.help  For a complete list of ACPI-related extensions.

Reference
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/acpi-debugging