Skip to content

Commit dd218f5

Browse files
authored
Various fixes and improvements to UefiExt (#78)
## Description Contains the following fixes and improvements 1. Created simple `!monitor` command for invoking GDB monitor commands without the tedious `.exdicmd target:0:...` command. This will also clean up the output and capture output even if verbose output is disabled. 2. Add support for a Rust debugger environment 3. in-progress implementation of ELF header dumping 4. Fixed issue with image magic size comparison. 5. Switch `!AdvLog` to use local definition to support parsing without C symbols. 6. Implemented environment autodetection by capture exdicmd response output. - [ ] Impacts functionality? - [ ] Impacts security? - [ ] Breaking change? - [ ] Includes tests? - [ ] Includes documentation? ## How This Was Tested Tested locally ## Integration Instructions N/A
1 parent 37502c2 commit dd218f5

6 files changed

Lines changed: 364 additions & 58 deletions

File tree

UefiDbgExt/memory.cpp

Lines changed: 94 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ Module Name:
2121
//
2222

2323
#pragma pack (push, 1)
24+
typedef struct {
25+
UINT16 Year;
26+
UINT8 Month;
27+
UINT8 Day;
28+
UINT8 Hour;
29+
UINT8 Minute;
30+
UINT8 Second;
31+
UINT8 Pad1;
32+
UINT32 Nanosecond;
33+
INT16 TimeZone;
34+
UINT8 Daylight;
35+
UINT8 Pad2;
36+
} EFI_TIME;
37+
2438
typedef struct {
2539
UINT32 Signature; // Signature
2640
UINT8 MajorVersion; // Major version of advanced logger message structure
@@ -33,6 +47,29 @@ typedef struct {
3347
// used to calculate the address of the Message
3448
// CHAR MessageText[]; // Message Text
3549
} ADVANCED_LOGGER_MESSAGE_ENTRY_V2;
50+
51+
typedef volatile struct {
52+
UINT32 Signature; // Signature 'ALOG'
53+
UINT16 Version; // Current Version
54+
UINT16 Reserved[3]; // Reserved for future
55+
UINT32 LogBufferOffset; // Offset from LoggerInfo to start of log, expected to be the size of this structure 8 byte aligned
56+
UINT32 Reserved4;
57+
UINT32 LogCurrentOffset; // Offset from LoggerInfo to where to store next log entry.
58+
UINT32 DiscardedSize; // Number of bytes of messages missed
59+
UINT32 LogBufferSize; // Size of allocated buffer
60+
BOOLEAN InPermanentRAM; // Log in permanent RAM
61+
BOOLEAN AtRuntime; // After ExitBootServices
62+
BOOLEAN GoneVirtual; // After VirtualAddressChange
63+
BOOLEAN HdwPortInitialized; // HdwPort initialized
64+
BOOLEAN HdwPortDisabled; // HdwPort is Disabled
65+
BOOLEAN Reserved2[3]; //
66+
UINT64 TimerFrequency; // Ticks per second for log timing
67+
UINT64 TicksAtTime; // Ticks when Time Acquired
68+
EFI_TIME Time; // Uefi Time Field
69+
UINT32 HwPrintLevel; // Logging level to be printed at hw port
70+
UINT32 Reserved3; //
71+
} ADVANCED_LOGGER_INFO;
72+
3673
#pragma pack (pop)
3774

3875
PCSTR MemoryTypeString[] = {
@@ -262,6 +299,7 @@ advlog (
262299
ULONG Offset;
263300
ULONG End;
264301
ADVANCED_LOGGER_MESSAGE_ENTRY_V2 *Entry;
302+
ADVANCED_LOGGER_INFO Info = { 0 };
265303

266304
// NOTE: This implementation is a crude first past, The following should be done
267305
// in the future.
@@ -296,8 +334,9 @@ advlog (
296334
goto Exit;
297335
}
298336

299-
GetFieldValue (InfoAddress, "ADVANCED_LOGGER_INFO", "Version", Version);
300-
GetFieldValue (InfoAddress, "ADVANCED_LOGGER_INFO", "LogBufferSize", LogBufferSize);
337+
ReadMemory (InfoAddress, (PVOID)&Info, sizeof (Info), &BytesRead);
338+
Version = Info.Version;
339+
LogBufferSize = Info.LogBufferSize;
301340

302341
g_ExtControl->ControlledOutput (
303342
DEBUG_OUTCTL_AMBIENT_DML,
@@ -307,7 +346,7 @@ advlog (
307346
InfoAddress
308347
);
309348

310-
dprintf ("Version: %d\n", Version);
349+
dprintf ("Version: %d\n", Info.Version);
311350
dprintf ("Size: 0x%x bytes\n", LogBufferSize);
312351

313352
if (LogBufferSize == 0) {
@@ -319,63 +358,70 @@ advlog (
319358
if (Version == 4) {
320359
GetFieldValue (InfoAddress, "ADVANCED_LOGGER_INFO", "LogBuffer", EntryAddress);
321360
GetFieldValue (InfoAddress, "ADVANCED_LOGGER_INFO", "LogCurrent", EndAddress);
322-
if (EndAddress < EntryAddress) {
323-
dprintf ("Looped logs not yet implemented in extension!\n");
324-
Result = ERROR_NOT_SUPPORTED;
325-
goto Exit;
326-
} else {
327-
// non-loop optimization, only download through the last message.
328-
LogBufferSize = min (LogBufferSize, (ULONG)(EndAddress - InfoAddress));
329-
}
330-
331-
LogBuffer = (CHAR *)malloc (LogBufferSize);
361+
} else if (Version == 5) {
362+
EntryAddress = InfoAddress + Info.LogBufferOffset;
363+
EndAddress = InfoAddress + Info.LogCurrentOffset;
364+
} else {
365+
dprintf ("\nVersion not implemented in debug extension!\n");
366+
Result = ERROR_NOT_SUPPORTED;
367+
goto Exit;
368+
}
332369

333-
// Output() forces IO flush to inform user.
334-
g_ExtControl->Output (DEBUG_OUTPUT_NORMAL, "Reading log (0x%x bytes) ... \n", LogBufferSize);
335-
ReadMemory (InfoAddress, LogBuffer, LogBufferSize, &BytesRead);
336-
if (BytesRead != LogBufferSize) {
337-
dprintf ("Failed to read log memory!\n");
338-
Result = ERROR_BAD_LENGTH;
339-
goto Exit;
340-
}
370+
if (EndAddress < EntryAddress) {
371+
dprintf ("Looped logs not yet implemented in extension!\n");
372+
Result = ERROR_NOT_SUPPORTED;
373+
goto Exit;
374+
} else {
375+
// non-loop optimization, only download through the last message.
376+
LogBufferSize = min (LogBufferSize, (ULONG)(EndAddress - InfoAddress));
377+
}
341378

342-
Offset = (ULONG)(EntryAddress - InfoAddress);
343-
End = (ULONG)(EndAddress - InfoAddress);
379+
LogBuffer = (CHAR *)malloc (LogBufferSize);
344380

345-
dprintf ("\n------------------------------------------------------------------------------\n");
346-
BOOLEAN PrevNL = TRUE;
347-
while (Offset < End) {
348-
Entry = (ADVANCED_LOGGER_MESSAGE_ENTRY_V2 *)(LogBuffer + Offset);
349-
if (Entry->Signature != 0x324d4c41) {
350-
dprintf ("\nBad message signature!!\n");
351-
break;
352-
}
381+
// Output() forces IO flush to inform user.
382+
g_ExtControl->Output (DEBUG_OUTPUT_NORMAL, "Reading log (0x%x bytes) ... \n", LogBufferSize);
383+
ReadMemory (InfoAddress, LogBuffer, LogBufferSize, &BytesRead);
384+
if (BytesRead != LogBufferSize) {
385+
dprintf ("Failed to read log memory!\n");
386+
Result = ERROR_BAD_LENGTH;
387+
goto Exit;
388+
}
353389

354-
ULONG StringEnd = Offset + Entry->MessageOffset + Entry->MessageLen;
355-
CHAR Temp = LogBuffer[StringEnd];
356-
LogBuffer[StringEnd] = 0;
390+
Offset = (ULONG)(EntryAddress - InfoAddress);
391+
End = (ULONG)(EndAddress - InfoAddress);
357392

358-
if (PrevNL) {
359-
dprintf (
360-
"%-8s| %-8s| ",
361-
(Entry->Phase < PHASE_COUNT ? PhaseStrings[Entry->Phase] : "UNK"),
362-
ErrorLevelToString (Entry->DebugLevel)
363-
);
364-
}
393+
dprintf ("\n------------------------------------------------------------------------------\n");
394+
BOOLEAN PrevNL = TRUE;
365395

366-
dprintf ("%s", LogBuffer + Offset + Entry->MessageOffset);
367-
PrevNL = (LogBuffer[StringEnd - 1] == '\n');
396+
while (Offset + sizeof (ADVANCED_LOGGER_MESSAGE_ENTRY_V2) <= End) {
397+
Entry = (ADVANCED_LOGGER_MESSAGE_ENTRY_V2 *)(LogBuffer + Offset);
398+
if (Entry->Signature != 0x324d4c41) {
399+
dprintf ("\nBad message signature!! Entry Offset: 0x%x\n", Offset);
400+
break;
401+
}
368402

369-
LogBuffer[StringEnd] = Temp;
403+
ULONG StringEnd = Offset + Entry->MessageOffset + Entry->MessageLen;
404+
CHAR Temp = LogBuffer[StringEnd];
405+
LogBuffer[StringEnd] = 0;
370406

371-
Offset = ALIGN_UP (Offset + Entry->MessageOffset + Entry->MessageLen, 8);
407+
if (PrevNL) {
408+
dprintf (
409+
"%-8s| %-8s| ",
410+
(Entry->Phase < PHASE_COUNT ? PhaseStrings[Entry->Phase] : "UNK"),
411+
ErrorLevelToString (Entry->DebugLevel)
412+
);
372413
}
373414

374-
dprintf ("\n------------------------------------------------------------------------------\n");
375-
} else {
376-
dprintf ("\nVersion not implemented in debug extension!\n");
415+
dprintf ("%s", LogBuffer + Offset + Entry->MessageOffset);
416+
PrevNL = (LogBuffer[StringEnd - 1] == '\n');
417+
418+
LogBuffer[StringEnd] = Temp;
419+
420+
Offset = ALIGN_UP (Offset + Entry->MessageOffset + Entry->MessageLen, 8);
377421
}
378422

423+
dprintf ("\n------------------------------------------------------------------------------\n");
424+
379425
Result = S_OK;
380426

381427
Exit:

UefiDbgExt/modules.cpp

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ FindModuleBackwards (
2626
CHAR Command[512];
2727
ULONG64 MaxSize;
2828
ULONG32 Check;
29-
CONST ULONG32 Magic = 0x5A4D; // MZ
29+
CONST ULONG32 Magic = 0x5A4D; // MZ
30+
CONST ULONG32 ElfMagic = 0x464C457F; // 0x7F_ELF
3031
ULONG BytesRead;
3132
HRESULT Result;
3233
ULONG64 Base;
@@ -50,14 +51,28 @@ FindModuleBackwards (
5051
for ( ; Address >= MinAddress; Address -= PAGE_SIZE) {
5152
Check = 0;
5253
ReadMemory (Address, &Check, sizeof (Check), &BytesRead);
53-
if ((BytesRead == sizeof (Check)) && (Check == Magic)) {
54+
if (BytesRead != sizeof (Check)) {
55+
break;
56+
}
57+
58+
if ((Check & 0xFFFF) == Magic) {
5459
sprintf_s (&Command[0], sizeof (Command), ".imgscan /l /r %I64x %I64x", Address, Address + 0xFFF);
5560
g_ExtControl->Execute (
5661
DEBUG_OUTCTL_ALL_CLIENTS,
5762
&Command[0],
5863
DEBUG_EXECUTE_DEFAULT
5964
);
6065

66+
Result = S_OK;
67+
break;
68+
} else if (Check == ElfMagic) {
69+
sprintf_s (&Command[0], sizeof (Command), "!uefiext.elf %I64x", Address);
70+
g_ExtControl->Execute (
71+
DEBUG_OUTCTL_ALL_CLIENTS,
72+
&Command[0],
73+
DEBUG_EXECUTE_DEFAULT
74+
);
75+
6176
Result = S_OK;
6277
break;
6378
}
@@ -238,3 +253,101 @@ findall (
238253
EXIT_API ();
239254
return S_OK;
240255
}
256+
257+
#pragma pack (push, 1)
258+
typedef struct _ELF_HEADER_64 {
259+
unsigned char e_ident[16]; // 0x74 + ELF
260+
UINT16 e_type;
261+
UINT16 e_machine;
262+
UINT32 e_version;
263+
UINT64 e_entry;
264+
UINT64 e_phoff;
265+
UINT64 e_shoff;
266+
UINT32 e_flags;
267+
UINT16 e_ehsize;
268+
UINT16 e_phentsize;
269+
UINT16 e_phnum;
270+
UINT16 e_shentsize;
271+
UINT16 e_shnum;
272+
UINT16 e_shstrndx;
273+
} ELF_HEADER_64;
274+
C_ASSERT (sizeof (ELF_HEADER_64) == 64);
275+
276+
typedef struct _ELF_SECTION_64 {
277+
UINT32 sh_name;
278+
UINT16 e_type;
279+
UINT16 e_machine;
280+
UINT32 e_version;
281+
UINT64 e_entry;
282+
UINT64 e_phoff;
283+
UINT64 e_shoff;
284+
UINT32 e_flags;
285+
UINT16 e_ehsize;
286+
UINT16 e_phentsize;
287+
UINT16 e_phnum;
288+
UINT16 e_shentsize;
289+
UINT16 e_shnum;
290+
UINT16 e_shstrndx;
291+
} ELF_SECTION_64;
292+
293+
#pragma pack (pop)
294+
295+
HRESULT CALLBACK
296+
elf (
297+
PDEBUG_CLIENT4 Client,
298+
PCSTR args
299+
)
300+
{
301+
ULONG64 Address;
302+
ELF_HEADER_64 Header = { 0 };
303+
ELF_SECTION_64 *Section;
304+
ULONG BytesRead = 0;
305+
306+
INIT_API ();
307+
308+
if (strlen (args) == 0) {
309+
dprintf ("Usage: !uefiext.elf [Address]\n");
310+
return ERROR_INVALID_PARAMETER;
311+
}
312+
313+
Address = GetExpression (args);
314+
if ((Address == 0) || (Address == (-1))) {
315+
dprintf ("Invalid address!\n");
316+
dprintf ("Usage: !uefiext.elf [Address]\n");
317+
return ERROR_INVALID_PARAMETER;
318+
}
319+
320+
ReadMemory (Address, &Header, sizeof (Header), &BytesRead);
321+
if (BytesRead != sizeof (Header)) {
322+
dprintf ("Failed to read header!\n");
323+
return ERROR_BAD_ARGUMENTS;
324+
}
325+
326+
if ((Header.e_ident[0] != 0x7F) || (Header.e_ident[1] != 'E') || (Header.e_ident[2] != 'L') || (Header.e_ident[3] != 'F')) {
327+
dprintf ("Invalid ELF header! Magic did not match.\n");
328+
return ERROR_INVALID_DATA;
329+
}
330+
331+
dprintf ("ELF Header @ %llx\n", Address);
332+
dprintf ("------------------------------------\n");
333+
dprintf ("Type 0x%x\n", Header.e_type);
334+
dprintf ("Machine 0x%x\n", Header.e_machine);
335+
dprintf ("Version 0x%x\n", Header.e_version);
336+
dprintf ("Entry 0x%llx\n", Header.e_entry);
337+
dprintf ("Program Table Offset 0x%llx\n", Header.e_phoff);
338+
dprintf ("Section Table Offset 0x%llx\n", Header.e_shoff);
339+
dprintf ("Flags 0x%x\n", Header.e_flags);
340+
dprintf ("Header Size 0x%x\n", Header.e_ehsize);
341+
dprintf ("Program Header Size 0x%x\n", Header.e_phentsize);
342+
dprintf ("Program Header Num 0x%x\n", Header.e_phnum);
343+
dprintf ("Section Header Size 0x%x\n", Header.e_shentsize);
344+
dprintf ("Section Header Num 0x%x\n", Header.e_shnum);
345+
dprintf ("Section Names Index 0x%x\n", Header.e_shstrndx);
346+
dprintf ("------------------------------------\n\n");
347+
348+
// Print sections.
349+
Section = (ELF_SECTION_64 *)(Address + Header.e_phoff);
350+
351+
EXIT_API ();
352+
return S_OK;
353+
}

UefiDbgExt/swdebug.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,12 @@ modulebreak (
4444

4545
INIT_API ();
4646

47-
sprintf_s (Command, sizeof (Command), ".exdicmd target:0:b%s", args);
47+
if (RUST == gUefiEnv) {
48+
sprintf_s (Command, sizeof (Command), ".exdicmd target:0:mod break %s", args);
49+
} else {
50+
sprintf_s (Command, sizeof (Command), ".exdicmd target:0:b%s", args);
51+
}
52+
4853
g_ExtControl->Execute (
4954
DEBUG_OUTCTL_ALL_CLIENTS,
5055
Command,
@@ -138,3 +143,20 @@ reboot (
138143
EXIT_API ();
139144
return S_OK;
140145
}
146+
147+
HRESULT CALLBACK
148+
monitor (
149+
PDEBUG_CLIENT4 Client,
150+
PCSTR args
151+
)
152+
{
153+
PSTR Response;
154+
155+
INIT_API ();
156+
157+
Response = MonitorCommandWithOutput (Client, args);
158+
dprintf ("%s\n", Response);
159+
160+
EXIT_API ();
161+
return S_OK;
162+
}

0 commit comments

Comments
 (0)