# MultiSkuDistinctionPei -- Multi-SKU Distinction PEI Module

## Overview

This PEIM detects the platform SKU (Stock Keeping Unit / hardware variant) by
reading SKU configuration from CMOS and/or a GUID-extended HOB installed by
an earlier PEIM (likely from the CrystalRidge chipset initialization). It then
installs a PPI via EFI_PEI_SERVICES to advertise the SKU identity so that
downstream PEIMs can adapt their behavior.

**Key Insight:** The module has two code paths:
- A "HOB-provisioned" path where a previous PEIM (CrystalRidge) writes SKU
  data into a GUID HOB with sentinel 0x55
- A "default" path where SKU PPI is installed with a notification mechanism
  for delayed SKU provisioning

## Module Information

| Field | Value |
|-------|-------|
| Module Name | MultiSkuDistinctionPei.efi |
| PE File Index | 0419 |
| Architecture | IA32 (32-bit) |
| Base Address | 0xffe6b0f4 |
| Image Size | 0xaa0 |
| Total Functions | 19 (all renamed) |
| Total Strings | 21 |
| MD5 | a9e8b3e80a18ca6defecd3a579772108 |
| SHA256 | 40ba8d607cf770ea8ddf835906301ae8c3f03e4c7185a2e1f35d58c4f28bab6e |

## GUIDs Used

| GUID | Value | Purpose |
|------|-------|---------|
| gSkuPeiServiceGuid | {36232936-0e76-31c8-a13a-3af2fc1c3932} | Debug print PPI service lookup |
| gSkuMatchGuid | {8a0d6b86-64f3-4dc2-a483-4987-71dfb7fd} | GUID-extended HOB identifier for SKU data |
| gSkuNotificationGuid | {9a7174ce-f357-4142-abbf-31c6-a5440be0} | PPI notification GUID used for default SKU path |

## Segment Layout

| Segment | Start | End | Size | Permissions |
|---------|-------|-----|------|-------------|
| HEADER | 0xffe6b0f4 | 0xffe6b354 | 0x260 | --- |
| .text | 0xffe6b354 | 0xffe6b7b4 | 0x460 | rx |
| .rdata | 0xffe6b7b4 | 0xffe6baf4 | 0x340 | r |
| .data | 0xffe6baf4 | 0xffe6bb54 | 0x60 | rw |
| .reloc | 0xffe6bb54 | 0xffe6bb94 | 0x40 | r |
| GAP | 0xffe6bb94 | 0xffe6c0f4 | 0x560 | rw |

## Function Map

| Address | Name | Size | Type | Description |
|---------|------|------|------|-------------|
| 0xffe6b354 | SetMem | 21 | leaf | memset wrapper |
| 0xffe6b374 | SetMem32_Pair | 32 | library | SetMem32 in reverse-order pairs |
| 0xffe6b394 | SetMem32 | 24 | leaf | memset32 wrapper |
| 0xffe6b3b4 | CopyMem | 96 | leaf | memmove with overlap handling |
| 0xffe6b414 | _ModuleEntryPoint | 116 | complex | **Main entry** alloc buffer, SkuInit, dispatch PPI |
| 0xffe6b488 | InstallSkuPpi | 68 | complex | Install default or notification SKU PPI |
| 0xffe6b4cc | GetDebugInstance | 49 | wrapper | Locate debug PPI via PeiServices->LocatePpi |
| 0xffe6b4fd | DebugPrint | 42 | complex | Conditional print with level mask check |
| 0xffe6b527 | PeiServicesNotify | 30 | wrapper | Call debug assert handler |
| 0xffe6b545 | SkuInit | 54 | complex | Read 3 SKU bytes from CrystalRidge HOB |
| 0xffe6b57b | EntryPointStub | 12 | wrapper | PPI callback -> InstallSkuPpi |
| 0xffe6b587 | GetSkuFromCmos | 79 | leaf | Read SKU from CMOS 0x4A or HW reg 0xFEDAF0490 |
| 0xffe6b5d6 | IsGuidMatch | 100 | complex | Compare 2 GUIDs via ReadUnaligned64 |
| 0xffe6b63a | GetHobList | 110 | complex | Get HOB list via PeiServices->GetHobList |
| 0xffe6b6a8 | FindHobByType | 69 | complex | Walk HOB list for type match |
| 0xffe6b6ed | FindMatchingHob | 53 | complex | Find CrystalRidge GUID-extended HOB matching gSkuMatchGuid |
| 0xffe6b722 | GetPeiServices | 50 | complex | Get PEI Services via IDT table pointer |
| 0xffe6b754 | ReadUnaligned64 | 44 | wrapper | Read 8 bytes from potentially unaligned ptr |
| 0xffe6b780 | ReadIdtr | 36 | leaf | __sidt instruction wrapper |

## Call Flow

```
_ModuleEntryPoint (0xffe6b414)
  |
  +-- (*PeiServices)->AllocatePages()   -- Allocate boot buffer
  |
  +-- SkuInit() (0xffe6b545)
  |     +-- FindMatchingHob() (0xffe6b6ed)
  |           +-- GetHobList() (0xffe6b63a)
  |           |     +-- GetPeiServices() (0xffe6b722)
  |           |     |     +-- ReadIdtr() (0xffe6b780)
  |           |     +-- (*PeiServices)->GetHobList()
  |           +-- FindHobByType() (0xffe6b6a8)
  |           +-- IsGuidMatch() (0xffe6b5d6)
  |                 +-- ReadUnaligned64() (0xffe6b754) [x4]
  |
  +-- [sentinel == 0x55] --> (*PeiServices)->InstallPpi (active path)
  +-- [sentinel != 0x55] --> InstallSkuPpi() (0xffe6b488)
        |
        +-- DebugPrint()
        |     +-- GetDebugInstance() (0xffe6b4cc)
        |     |     +-- GetPeiServices()
        |     |     +-- (*PeiServices)->LocatePpi()
        |     +-- GetSkuFromCmos() (0xffe6b587) -- check debug mask
        |
        +-- SkuInit()
        +-- (*PeiServices)->NotifyPpi() -- install default PPI
```

## Execution Flow Details

### Phase 1: Module Entry

1. **Allocate buffer**: `PeiServices->AllocatePages (EfiBootServicesData, 52, &Buffer)`
2. **Write revision data**: The allocated buffer receives platform revision data
   and a sentinel byte (0x55) at offset 16.
3. **SkuInit**: Reads the CrystalRidge SKU HOB. If found, 3 SKU identifier
   bytes (at HOB offsets 48, 49, 50) are copied into a local buffer.
4. **Decision**: If `SkuBuffer[24] == 0x55` (sentinel present):
   - Install the active SKU PPI descriptor
   - This path means CrystalRidge-provisioned SKU data is already available
   - Otherwise: call `InstallSkuPpi()` for the default path

### Phase 2: InstallSkuPpi (Default Path)

1. Prints `"InstallSkuPpi is called\n"` via debug print
2. Tries `SkuInit()` again (defensive)
3. If `SkuBuffer[24] != 0x55`:
   - Installs the "default" PPI notification via `PeiServices->NotifyPpi()`
   - This causes `EntryPointStub(0xffe6b57b)` to fire when the PPI is installed
   - EntryPointStub re-enters `InstallSkuPpi()` recursively

### SKU Detection: GetSkuFromCmos

Hardware-level SKU detection with CMOS fallback:

1. **CMOS register 0x4A**: Read via I/O ports 0x70/0x71
   - NMI bit (0x80) is preserved from original CMOS index
2. **If value <= 3**: Return directly (small SKU IDs 0-3)
   - value 0x00 -> return 0 (SKU not found)
   - value 0x01 -> return 1 (SKU found)
3. **If value == 0**: Fallback to MMIO at **0xFEDAF0490**
   - Mask bit 1, OR with 1
   - `result = (MMIO & 2) | 1`
   - If result is 0x01, SKU is valid
4. **If value == 0xFF**: Return 0 (SKU invalid)
5. **Otherwise**: Return EFI error codes

## Library Dependencies (internal implementations)

| Function | EDK2 Source |
|----------|-------------|
| SetMem | MdePkg/Library/BaseMemoryLib |
| SetMem32_Pair | MdePkg/Library/BaseMemoryLib |
| SetMem32 | MdePkg/Library/BaseMemoryLib |
| CopyMem | MdePkg/Library/BaseMemoryLib |
| ReadUnaligned64 | MdePkg/Library/BaseLib/Unaligned.c |
| ReadIdtr | MdePkg/Library/BaseLib/X86ReadIdtr.c |
| GetPeiServices | MdePkg/Library/PeiServicesTablePointerLibIdt |
| GetHobList / FindHobByType / IsGuidMatch | MdePkg/Library/PeiHobLib/HobLib.c |
| DebugPrint / GetDebugInstance / PeiServicesNotify | MdePkg/Library/PeiDebugLib |

## Hardware Addresses Referenced

| Address | Purpose |
|---------|---------|
| 0x70 (I/O) | CMOS index register |
| 0x71 (I/O) | CMOS data register |
| 0xFEDAF0490 (MMIO) | Fallback SKU hardware register (LPC/Firmware Hub) |

## Notes

- The module has **no imported functions** -- all dependencies are linked
  statically as internal implementations.
- The PEI Services Table Pointer is obtained via the **IDT pointer trick**:
  the PEI Services pointer is stored 4 bytes before the IDT base address.
- GUID comparison uses **unaligned 64-bit reads** instead of CompareGuid(),
  which is a common pattern in EDK2 BaseLib implementations where full GUID
  comparison is replaced with 2 x 64-bit integer comparisons.
- The module is part of the **Lenovo CrystalRidge** platform initialization,
  providing SKU distinction so that subsequent PEIMs (especially those in
  the CrystalRidge PEI phase) can select the correct configuration for
  the detected hardware variant.
- **32 functions renamed** in total (was 18 unnamed + 1 entry point).