# BmcLanConfig UEFI Module Analysis

## Overview

**Module:** BmcLanConfig.efi (PE32+ image, DXE driver)
**Source:** HR650X BIOS -- Lenovo ThinkSystem server
**Architecture:** x86-64
**Image Size:** 0x25c0 (9,664 bytes)
**MD5:** d4c865b5f727f727f3f3c45ac5ddc7a2
**SHA256:** 99bdd4660988c49b1083dd7285ad72fbda897f6ee5b903bf3bbb3275c1e9a392
**IDA Port:** 13339
**Index in PE collection:** 0253

## Purpose

This DXE (Driver eXecution Environment) module configures BMC (Baseboard Management Controller) LAN (Local Area Network) parameters during the UEFI boot process. It enumerates the available LAN channels on the BMC and for each active channel programs:

- Station IP address
- Subnet mask
- Default gateway (router) IP address
- Default gateway MAC address

The programming is done via IPMI (Intelligent Platform Management Interface) commands sent through the IPMI transport protocol, which is located via UEFI's `LocateProtocol()` boot service.

## Module Structure

### Segments

| Segment | Start | End | Size | Permissions | Content |
|---------|-------|-----|------|-------------|---------|
| HEADER | 0x000 | 0x280 | 0x280 | --- | PE/COFF header |
| .text | 0x280 | 0x1880 | 0x1600 | rx | Executable code |
| .rdata | 0x1880 | 0x1f20 | 0x6a0 | r | String data, GUIDs |
| .data | 0x1f20 | 0x2400 | 0x4e0 | rw | Protocol GUIDs, BSS |
| seg004 | 0x2400 | 0x24e0 | 0xe0 | r | Exception handling |
| .xdata | 0x24e0 | 0x25c0 | 0xe0 | r | Exception handling |
| GAP | 0x25c0 | 0x3000 | 0xa40 | rw | Gap/padding |

### Function Map (19 total, 18 unnamed -> renamed)

| Address | Original Name | Renamed Name | Size | Type | Description |
|---------|---------------|--------------|------|------|-------------|
| 0x280 | sub_280 | **InternalCopyMem** | 0x42 (66) | leaf | Optimized memcpy (qmemcpy with forward/backward overlap handling) |
| 0x350 | _ModuleEntryPoint | _ModuleEntryPoint | 0xa9 (169) | complex | UEFI standard entry: saves gImageHandle, gST, gBS, gRT; calls GetHobList then InitializeBmcLanConfig |
| 0x3FC | sub_3FC | **AsciiIpv4AddrToBytes** | 0x17e (382) | leaf | Parses UTF-16 IPv4 address string into 4 octets |
| 0x57C | sub_57C | **AsciiMacAddrToBytes** | 0x136 (310) | leaf | Parses UTF-16 MAC address string into 6 bytes |
| 0x6B4 | sub_6B4 | **IpmiSendCommandWithRetry** | 0x9b (155) | leaf | Sends IPMI command with up to 10 retries on busy |
| 0x750 | sub_750 | **IpmiSetLanConfigParams** | 0x180 (384) | complex | Programs all 4 LAN parameters for one channel |
| 0x8D0 | sub_8D0 | **IpmiSetLanConfigParamBytes** | 0x57 (87) | wrapper | Sets one LAN config parameter via IPMI |
| 0x928 | sub_928 | **IpmiGetLanConfigParamBytes** | 0x95 (149) | leaf | Reads one LAN config parameter from BMC |
| 0x9C0 | sub_9C0 | **IpmiGetChannelNumber** | 0x6f (111) | complex | Queries the BMC for the current channel number |
| 0xA30 | sub_A30 | **InitializeBmcLanConfig** | 0x8aa (2218) | complex | Main driver: discovers channels and programs LAN settings |
| 0x12DC | sub_12DC | **CopyMemWithAssert** | 0x9e (158) | complex | Memory copy with ASSERT bounds checking (MdePkg wrapper) |
| 0x137C | sub_137C | **GetDebugOutputProtocol** | 0x7f (127) | leaf | Locates debug output protocol from HOB |
| 0x13FC | sub_13FC | **DebugPrint** | 0x88 (136) | complex | Conditional debug print via CMOS debug level register (0x4B/0x70/0x71) |
| 0x1484 | sub_1484 | **ReportAssertionFailure** | 0x3e (62) | wrapper | Calls assertion handler on debug output protocol |
| 0x159C | sub_159C | **GetLanChannelNumbers** | 0x19a (410) | complex | Scans channels 1-11 for those with medium type 4 |
| 0x14C4 | sub_14C4 | **GetHobList** | 0xd6 (214) | complex | Locates HOB list from system table config table |
| 0x1738 | sub_1738 | **GetPcdProtocol** | 0x8c (140) | complex | Locates PCD protocol via LocateProtocol |
| 0x17C4 | sub_17C4 | **IsGuidMatch** | 0x6e (110) | wrapper | GUID comparison (first QWORD + second QWORD) |
| 0x1834 | sub_1834 | **ReadUnaligned64** | 0x2f (47) | wrapper | Reads UINT64 from potentially unaligned address |

### Call Graph

```
_ModuleEntryPoint (0x350)
  |
  +-> GetHobList (0x14C4)
  |     +-> IsGuidMatch (0x17C4)
  |           +-> ReadUnaligned64 (0x1834)
  |
  +-> InitializeBmcLanConfig (0xA30)
        |
        +-> GetLanChannelNumbers (0x159C)
        |     +-> IpmiGetChannelNumber (0x9C0)
        |     +-> IpmiSendCommandWithRetry (0x6B4)
        |     +-> CopyMemWithAssert (0x12DC)
        |     +-> DebugPrint (0x13FC)
        |           +-> GetDebugOutputProtocol (0x137C)
        |
        +-> IpmiSetLanConfigParams (0x750)
        |     +-> IpmiSendCommandWithRetry (0x6B4)
        |     +-> CopyMemWithAssert (0x12DC)
        |     +-> IpmiSetLanConfigParamBytes (0x8D0)
        |
        +-> DebugPrint (0x13FC)
```

## Key Data Structures

### Protocol GUIDs (in .data section)

| Address | Use | GUID Value |
|---------|-----|------------|
| 0x1F20 | IPMI Transport Protocol | {0x36232936, 0x0e76, 0x31c8, {0xa1, 0x3a, 0x3a, 0xf2, 0xfc, 0x1c, 0x39, 0x32}} |
| 0x1F30 | PCD Protocol | {0x11b34006, 0xd85b, 0x4d0a, {0xa2, 0x90, 0xd5, 0xa5, 0x71, 0x31, 0x0e, 0xf7}} |
| 0x1F60 | gEfiHobListGuid | {0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d}} |

### Global Variables (.data segment, zero-initialized BSS)

| Address | Symbol | Size | Purpose |
|---------|--------|------|---------|
| 0x23F0 | mIpmiTransport (qword_23F0) | 8 | IPMI transport protocol interface pointer |
| 0x1FA8 | mHobList (qword_1FA8) | 8 | HOB list pointer |
| 0x1FA0 | mDebugProtocol (qword_1FA0) | 8 | Debug output protocol pointer |
| 0x1FB0 | mPcdProtocol (qword_1FB0) | 8 | PCD protocol pointer |
| 0x2052 | byte_2052 | 1 | Channel number buffer byte |
| 0x1FD2 | byte_1FD2 | 1 | Channel number buffer byte |
| 0x1F80 | gST (SystemTable) | 8 | EFI System Table |
| 0x1F88 | gBS (BootServices) | 8 | EFI Boot Services table |
| 0x1F90 | gImageHandle | 8 | Image handle |
| 0x1F98 | gRT (RuntimeServices) | 8 | EFI Runtime Services table |

### ServerSetup Configuration Data (at 0x1940)

The string "ServerSetup" at 0x1940 (in UTF-16) appears to identify the HII variable
that stores the BMC LAN configuration data. The configuration data is organized as
a 19-byte block per channel:

```
Offset  Size  Field
------  ----  -----
 0       1    Channel number
 1       4    Station IP address
 5       4    Subnet mask
 9       4    Default gateway IP address
13       6    Default gateway MAC address
```

The `######################` string (0x1958) is a debug output separator that
appears before each channel's configuration dump.

## IPMI Commands Used

### Set LAN Configuration Parameters
- **NetFn:** 0x0C (LAN / Chassis)
- **Command:** 0x01 (Set LAN Configuration Parameters)
- **LUN:** 1 (BMC)
- **Request format:** [ChannelNumber, ParameterSelector, ParameterBytes...]
- **Parameters programmed:**
  - Selector 3: Station IP address (4 bytes)
  - Selector 6: Subnet mask (4 bytes)
  - Selector 12: Default gateway IP (4 bytes)
  - Selector 13: Default gateway MAC (6 bytes)

### Get LAN Configuration Parameters
- **NetFn:** 0x0C (LAN)
- **Command:** 0x02 (Get LAN Configuration Parameters)
- **LUN:** 2 (OEM)
- **Request:** [ChannelNumber, ParamSelector, SetSelector]
- **Response:** [ParameterData...] with bit 7 indicating parameter revision

### Get Channel Number (Application command)
- **NetFn:** 0x06 (Application)
- **Command:** 0x42 (Get Channel Number)
- **LUN:** 66 (OEM-specific)
- **Medium type check:** Response byte bits [6:0] == 4 means dedicated LAN

### Retry Logic
- Commands retry up to 10 times when the BMC returns a "busy" status
  (checked via bits [1:0] of the response).
- 1-second delay between retries via `gBS->Stall(1000 * 1000)`.

## String Reference

| Address | String | Usage |
|---------|--------|-------|
| 0x1880 | "ASSERT_EFI_ERROR (Status = %r)" | Debug assertion macro |
| 0x18A8 | "!EFI_ERROR (Status)" | Assert condition string |
| 0x18D0 | "InitializeBmcLanConfig" | Function name for debug |
| 0x18F0 | "%a ChannelNumberBuffer[0]: %x ChannelNumberBuffer[1]: %x ChannelCount = %x" | Debug output of channel discovery |
| 0x1940 | "ServerSetup" | HII variable name for config data |
| 0x1958 | "#########################" | Debug separator |
| 0x19C0 | "### StationIp: %d %d %d %d" | Debug: IP address dump |
| 0x19E0 | "### SubnetMask: %d %d %d %d" | Debug: subnet mask dump |
| 0x1A00 | "### RouterIp: %d %d %d %d" | Debug: gateway IP dump |
| 0x1A20 | "### Router MAC: %x %x %x %x %x %x" | Debug: gateway MAC dump |
| 0x1CB8 | "GetLanChannelNumber" | Function name for debug |
| 0x1AA0 | "MdePkg/Library/UefiBootServicesTableLib.c" | Source path (assertion) |
| 0x1BD8 | "MdePkg/Library/BaseMemoryLibRepStr/CopyMemWrapper.c" | Source path (assertion) |
| 0x1C70 | "MdePkg/Library/DxeHobLib/HobLib.c" | Source path (assertion) |
| 0x1D20 | "MdePkg/Library/DxePcdLib/DxePcdLib.c" | Source path (assertion) |
| 0x1D68 | "MdePkg/Library/BaseLib/Unaligned.c" | Source path (assertion) |

## Analysis Notes

1. **This module is a UEFI DXE driver**, not a standalone executable. It depends on the
   UEFI boot/runtime services provided by the firmware.

2. **IPMI transport protocol** is located via LocateProtocol() using the GUID at
   0x1F20. The protocol interface pointer is stored in `qword_23F0` (mIpmiTransport).

3. **Debug output** uses a CMOS-based debug level check (I/O ports 0x70/0x71):
   - Reads register 0x4B of CMOS
   - Checks debug level bits
   - Only prints debug messages if the level is set appropriately

4. **Channel discovery** scans IPMB channels 1 through 11, querying each for
   medium type. Only channels with medium type 4 (dedicated LAN, likely NC-SI or
   USB-over-LAN) are configured.

5. **The "ServerSetup" string** at 0x1940 is in UTF-16 format and is likely the
   name of an HII variable or form that stores the LAN configuration data input
   by the user through the BIOS setup menu.

6. **Build environment:** The source paths (e:\\hs\\MdePkg\\...) indicate this was
   built using a Windows-based EDK II build environment with the MdePkg and
   MdeModulePkg packages from the UEFI firmware development kit.

7. **Assertion behavior:** All library functions include ASSERT() calls that
   trigger `ReportAssertionFailure()`. This is standard UEFI debug/free builds.
   In a release build, these assertions are compiled out.

## Related IPMI Specification References

- IPMI Specification v2.0, Section 18: LAN Configuration Parameters
- IPMI Specification v2.0, Section 22.20: Get/Set LAN Configuration Parameters commands
- DMTF NC-SI (Network Controller Sideband Interface) specification for the sideband
  channel medium type (type 4)