Re: [edk2] UEFI Shell + startup.nsh
Rafael Machado writes: > I have a question. > Considering I have a PXE server that my client downloads a shell.efi app. > Considering also that I need to execute a .nsh script, but I their is no > media at the system. (no usb or storage device attached) > > Is there any way to embed a startup.nsh at the shell.efi application? > As far as I know with PXE just one file is downloaded and executed. (I am > also checking how to use the EfiRamDisk protocol to create a temporary > place for the .nsh generated files.) You'd probably need to format your UEFI RAM disk with an FAT file system, download the .nsh script into it, then UEFI shell application would look for the startup script and then execute it. Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v3 1/3] MdeModulePkg/UdfDxe: Check 'Component Type' within a Path Component
Hi Hao Wu, On October 29, 2018 10:26:15 PM GMT-03:00, Hao Wu wrote: >REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1279 > >According to the ECMA-167 standard (3rd Edition - June 1997), Section >14.16.1.1, valid values are 1 to 5. All other values will be treated as >a >corrupted volume. > >This commit will add such check within function ResolveSymlink(). > >Cc: Leif Lindholm >Cc: Ruiyu Ni >Contributed-under: TianoCore Contribution Agreement 1.1 >Signed-off-by: Hao Wu >Reviewed-by: Paulo Alcantara >Reviewed-by: Star Zeng >--- > MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 7 +++ > 1 file changed, 7 insertions(+) > >diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >index b9ebddfe62..c15741a032 100644 >--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >@@ -2257,6 +2257,13 @@ ResolveSymlink ( > } > FileName[Index] = L'\0'; > break; >+default: >+ // >+ // Accoring to the ECMA-167 standard (3rd Edition - June 1997), >Section Minor typo: s/Accoring/According/ Paulo >+ // 14.16.1.1, all other values are reserved. >+ // >+ Status = EFI_VOLUME_CORRUPTED; >+ goto Error_Find_File; > } > > // -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] MdeModulePkg/UdfDxe: Additional checks for ResolveSymlink()
Hao Wu writes: > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1279 > > The commit will add 3 types of checks for function ResolveSymlink(): > > A. Check for the value of 'Component Type' field within a Path Component > > According to the ECMA-167 standard (3rd Edition - June 1997), Section > 14.16.1.1, valid values are 1 to 5. All other values will be treated as a > corrupted volume. > > B. Check for the content pointed by 'File' > > Since content within 'File' is the output data for ResolveSymlink(). > Checks is added to ensure the content in 'File' is valid. Otherwise, > possible null pointer dereference issue will occur during the subsequent > usage of the data returned by ResolveSymlink(). > > C. Check for possible memory double free/use after free case > > For codes: > > if (CompareMem ((VOID *), (VOID *)Parent, > sizeof (UDF_FILE_INFO)) != 0) { > CleanupFileInformation (); > } > > CopyMem ((VOID *), (VOID *)File, sizeof (UDF_FILE_INFO)); > > If the contents in 'PreviousFile' and 'File' are the same, call to > "CleanupFileInformation ();" will free the buffers in 'File' > as well. This will lead to potential memory double free/use after free > issues. > > Cc: Paulo Alcantara > Cc: Paulo Alcantara > Cc: Ruiyu Ni > Cc: Star Zeng > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Hao Wu > --- > .../Universal/Disk/UdfDxe/FileSystemOperations.c | 30 > -- > 1 file changed, 28 insertions(+), 2 deletions(-) > > diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c > b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c > index b9ebddfe62..a89e5ba9ff 100644 > --- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c > +++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c > @@ -2145,6 +2145,8 @@ ResolveSymlink ( >UINT8 CompressionId; >UDF_FILE_INFO PreviousFile; > > + ZeroMem ((VOID *)File, sizeof (UDF_FILE_INFO)); > + >// >// Symlink files on UDF volumes do not contain so much data other than >// Path Components which resolves to real filenames, so it's OK to read in > @@ -2257,6 +2259,13 @@ ResolveSymlink ( >} >FileName[Index] = L'\0'; >break; > +default: > + // > + // Accoring to the ECMA-167 standard (3rd Edition - June 1997), Section > + // 14.16.1.1, all other values are reserved. > + // > + Status = EFI_VOLUME_CORRUPTED; > + goto Error_Find_File; > } > > // > @@ -2281,8 +2290,18 @@ ResolveSymlink ( >break; > } > > -if (CompareMem ((VOID *), (VOID *)Parent, > -sizeof (UDF_FILE_INFO)) != 0) { > +// > +// Check the content in the file info pointed by File. > +// > +if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) { > + Status = EFI_VOLUME_CORRUPTED; > + goto Error_Find_File; > +} > + > +if ((CompareMem ((VOID *), (VOID *)Parent, > +sizeof (UDF_FILE_INFO)) != 0) && > +(CompareMem ((VOID *), (VOID *)File, > +sizeof (UDF_FILE_INFO)) != 0)) { >CleanupFileInformation (); > } > > @@ -2294,6 +2313,13 @@ ResolveSymlink ( > // >FreePool (ReadFileInfo.FileData); > > + // > + // Check the content in the resolved file info. > + // > + if ((File->FileEntry == NULL) || (File->FileIdentifierDesc == NULL)) { > +return EFI_VOLUME_CORRUPTED; > + } > + >return EFI_SUCCESS; > > Error_Find_File: Reviewed-by: Paulo Alcantara Thanks! Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v1 00/10] UDF: Bugfixes
Hao Wu writes: > The series will address a couple of bugs within the UDF related codes. > > Please refer to the log message of each commit for more details. > > Cc: Paulo Alcantara > Cc: Ruiyu Ni > Cc: Jiewen Yao > Cc: Star Zeng > > Hao Wu (10): > MdeModulePkg/PartitionDxe: Add check for underlying device block size > MdeModulePkg/UdfDxe: Refine boundary checks for file/path name string > MdeModulePkg/UdfDxe: Add boundary check the read of FE/EFE > MdeModulePkg/UdfDxe: Add boundary check for ComponentIdentifier decode > MdeModulePkg/UdfDxe: Add boundary check for getting volume (free) size > MdeModulePkg/UdfDxe: Correct behavior for UdfSetPosition() > MdeModulePkg/UdfDxe: Fix a typo within SetFileInfo() > MdeModulePkg/UdfDxe: Update GetInfo() for FS VolumeLabel info request > MdeModulePkg/UdfDxe: Add more check when getting PD from LongAd > MdeModulePkg/UdfDxe: Avoid possible use of already-freed data > > MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 28 +++ > MdeModulePkg/Universal/Disk/UdfDxe/File.c | 96 > MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 253 > ++-- > MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 63 - > MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf | 1 + > 5 files changed, 362 insertions(+), 79 deletions(-) For the series: Reviewed-by: Paulo Alcantara Thanks! Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v1 0/7] Code refinements in UdfDxe
Hi, Hao Wu writes: > This series will refine the codes in MdeModulePkg/Universal/Disk/UdfDxe > for: > > A. Refine asserts used for memory allocation failure and error cases that >are possible to happen. Will use error handling logic for them; > > B. Address some dead codes within this module. > > Cc: Paulo Alcantara > Cc: Ruiyu Ni > Cc: Star Zeng > > Hao Wu (7): > MdeModulePkg/UdfDxe: Use error handling for memory allocation failure > MdeModulePkg/UdfDxe: ASSERT for false positives of NULL ptr deref > MdeModulePkg/UdfDxe: Use error handling when fail to return LSN > MdeModulePkg/UdfDxe: Use debug msg instead of ASSERT in UdfOpen() > MdeModulePkg/UdfDxe: Handle dead codes in File.c > MdeModulePkg/UdfDxe: Remove dead codes in FileName.c > MdeModulePkg/UdfDxe: Handle dead codes in FileSystemOperations.c > > MdeModulePkg/Universal/Disk/UdfDxe/File.c | 19 ++- > MdeModulePkg/Universal/Disk/UdfDxe/FileName.c | 15 -- > MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 162 > +++- > 3 files changed, 142 insertions(+), 54 deletions(-) Looks good to me. Thanks! For the series: Reviewed-by: Paulo Alcantara Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
"Yao, Jiewen"writes: Hi Jiewen, > === > OVMF IA32: DXE worked, but SMM not. > > Since the page fault is only occurring in IA32 with no paging enabled > (default case), I suspect that when we don't have paging, we are unable > to successfully validate the memory address when it's i.e. outside SMRAM > - that is, we don't know when to stop unwinding the stack. > === > > For IA32 SMM, I am a little confused. > We unconditionally setup page table for SMM, no matter it is IA32 or X64. > > If you find a SMM driver running in a page-disable environment, it means, the > SMM CORE load the driver in SMRAM, but the SMM CPU driver has not rebased the > CPU yet. > SMM driver is still using the PageTable/GDT/IDT setup by DXE CPU > driver, not SMM CPU driver. OK - thanks for clarifying that. > Would you please double confirm what you have observed? > > You can just check the boot log file to see if PiSmmCpu driver has run > or not. Sure. I will do it and then get back to you once I got the results. Thanks Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
ers and, when we find an invalid return address (e.g. last valid frame), we stop the trace. With that, SMM is now working in X64. Since the page fault is only occurring in IA32 with no paging enabled (default case), I suspect that when we don't have paging, we are unable to successfully validate the memory address when it's i.e. outside SMRAM - that is, we don't know when to stop unwinding the stack. Any ideas on what might be causing that? Other than that, I'll try to do some more tests this weekend and come back with the results. (That's why I didn't send out the v6 yet) Repo: https://git.paulo.ac/pub/edk2.git Branch: stacktrace_v6 Thanks Paulo Thank you Yao Jiewen -Original Message- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo Alcantara Sent: Monday, January 15, 2018 8:23 AM To: edk2-devel@lists.01.org Cc: Rick Bramley <richard.bram...@hp.com>; Dong, Eric <eric.d...@intel.com>; Kimon Berlin <kimon.ber...@hp.com>; Andrew Fish <af...@apple.com>; Yao, Jiewen <jiewen@intel.com>; Diego Medaglia <diego.meag...@hp.com>; Laszlo Ersek <ler...@redhat.com> Subject: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling Hi, This series adds stack trace support during IA32 and X64 CPU exceptions. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. The current limitation is that it relies on available frame pointers (GCC only) in order to successfully unwind the stack. Jiewen, Thank you very much for your time on this. I've applied the changes you suggested, as well as tested it on IA32 PAE paging mode - it worked as expected. Other than that, I also tested the stack trace in SMM code by manually calling CpuBreakPoint() and then it broke with another exception (page fault). I didn't have much time to look into that, but what I've observed is that the page fault ocurred during the search of PE/COFF image base address (in PeCoffSearchImageBase). The function attempts to search for the image base from "Address" through 0, so any of those dereferenced addresses triggers the page fault. Do you know how we could fix that issue? Perhaps introducing a AddressValidationLib (as Brian suggested previously) and use it within PeCoffSearchImageBase()? I'd also like to thank Brian & Jeff for all the support! Thanks Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v5 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Kimon Berlin <kimon.ber...@hp.com> Cc: Diego Medaglia <diego.meag...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Brian Johnson <brian.john...@hpe.com> Cc: Jeff Fan <vanjeff_...@hotmail.com> Cc: Jiewen Yao <jiewen@intel.com> Cc: Paulo Alcantara <pa...@hp.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. v2 -> v3: * Fixed wrong assumption about "RIP < ImageBase" to start searching for another PE/COFF image. That is, RIP may point to lower and higher addresses for any other PE/COFF images. Both IA32 & X64. (Thanks Andrew & Jiewen) * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) v3 -> v4: * Validate all frame/stack pointer addresses before dereferencing them as requested by Brian & Jiewen. * Correctly print out IP addresses during the stack traces (by Jeff) v4 -> v5: * Fixed address calculations and improved code as suggested by Jiewen. * Fixed parameter validation as suggested by Brian. * Tested stack stack with IA32 PAE paging mode. Paulo Alcantara (8): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Add helper to validate memory addresses UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges UefiCpuPkg/CpuExceptionHandlerLib: Add early check in DumpStackContents UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 537 ++-- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 59 ++- UefiCpuPkg/Library/CpuEx
Re: [edk2] DMA Buffer write operation not persisted
On January 25, 2018 4:53:06 PM GMT-02:00, Rafael Machadowrote: >Hi everyone. > >I'm currently work on a task, and I need to write some data at a DMA >buffer. >At the UEFI Driver Writer's guide, at page 359 there is a sample code >of >how to do that. > >Considering that code and adapting to my scenario I got the following >function (some debug prints are present for clarification): > >EFI_STATUS >EFIAPI >DoBusMasterWrite ( > IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciIo, > IN UINT8 *HostAddress, > IN UINTN *Length, > IN UINT32 Value >) >{ > EFI_STATUS Status; > UINTN NumberOfBytes; > EFI_PHYSICAL_ADDRESS DeviceAddress; > VOID *Mapping; > UINT64 ReadValue; > > // > // Call Map() to retrieve the DeviceAddress to use for the bus > // master write operation. The Map() function may not support > // performing a DMA operation for the entire length, so it may > // be broken up into smaller DMA operations. > // > NumberOfBytes = *Length; > Status = PciIo->Map (PciIo, // This > > EfiPciIoOperationBusMasterCommonBuffer, // Operation >(VOID *)HostAddress, // HostAddress > , // NumberOfBytes > , //DeviceAddress > //Mapping); > > if (EFI_ERROR (Status)) { >return Status; > } > > // > // Write the data to the desired address > // This write operation also starts the DMA transaction > // > Status = PciIo->Mem.Write (PciIo, // This > EfiPciIoWidthUint32, // Width > *HostAddress, > 1, // Count >// Buffer > ); I'm not sure, but I think you're passing the wrong value to the 3rd parameter (Address). Shouldn't that be "(UINT64)(UINTN)HostAddress"? Paulo > > Print(L"NumberOfBytes: %d\r\n", NumberOfBytes); > Print(L"address: 0x%x\r\n", HostAddress); > Print(L"Value: 0x%x\r\n", Value); > Print(L"Status: %r\r\n", Status); > > if (EFI_ERROR (Status)) { >return Status; > } > > // > // The operations performed by PollMem() also flush all posted > // writes from the PCI bus master and through PCI-to-PCI bridges. > // > Status = PciIo->PollMem (PciIo, // This > EfiPciIoWidthUint32, // Width > *HostAddress, // Offset > 0x,// Mask > Value,// Value > EFI_TIMER_PERIOD_SECONDS >(1), // Timeout >// Result > ); > Print(L"Status2: %r\r\n", Status); > > if (EFI_ERROR (Status)) { >return Status; > } > > // > // Call Flush() to flush all write transactions to system memory > // > Status = PciIo->Flush (PciIo); > Print(L"Status3: %r\r\n", Status); > > if (EFI_ERROR (Status)) { >return Status; > } > > // > // Call Unmap() to complete the bus master write operation > // > Status = PciIo->Unmap (PciIo, Mapping); > Print(L"Status4: %r\r\n", Status); > > if (EFI_ERROR (Status)) { >return Status; > } > return Status; >} > >The output of this function is this: > NumberOfBytes: 4 > address: 0xCCCAC000 > Value: 0xA > Status: Success > Status2: Success > Status3: Success > Status4: Success > >The problem is that when I try to read this memory content using the >dmem >command at the efiShell the value 0xA cannot be found. Seems >something >is locking the DMA trasaction. >Can someone give me some light? > >Thanks and Regard >Rafael R. Machado >___ >edk2-devel mailing list >edk2-devel@lists.01.org >https://lists.01.org/mailman/listinfo/edk2-devel -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] EDK II debug question
On 1/20/2018 4:58 AM, JUNWEN JIA wrote: Hi: Could you please tell how to build assembly language using EDK2? I tried to create a .c file in AppPkg, but it goes like this: #include Void main() { _asm{} } I used X64 to compile this project, but it seems content like _asm{} is not supported. Do I need to add extra files? And where should I add them? AFAIK, inline assembly is not supported in X64 MSFT compiler. Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
Paulo Alcantara <pa...@paulo.ac> writes: >> 3) I am a little surprised on PeCoffSearchImageBase() issue. >> >> We have 4 PeCoffSearchImageBase() call in each arch. DumpImageModuleNames() >> calls twice and DumpStacktrace() calls twice. >> Do you know which specific one triggers the zero address #PF issue? >> >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\ArchExceptionHandler.c(547): >> ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\ArchExceptionHandler.c(613): >> ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\ArchExceptionHandler.c(682): >> ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\ArchExceptionHandler.c(741): >> ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\ArchExceptionHandler.c(540): >> ImageBase = PeCoffSearchImageBase (Rip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\ArchExceptionHandler.c(613): >> ImageBase = PeCoffSearchImageBase (Rip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\ArchExceptionHandler.c(710): >> ImageBase = PeCoffSearchImageBase (Rip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\ArchExceptionHandler.c(779): >> ImageBase = PeCoffSearchImageBase (Rip); >> > > When I saw the #PF when testing stack trace in SMM, I was running out of > time and I just saved the log file with the trace. I'm attaching the > log for you, but I'm still going to look into that issue when time > permits. Forgot to attach the log file. Done. :-) X64 Exception Type - 03(#BP - Breakpoint) CPU Apic ID - RIP - 7FF48151, CS - 0038, RFLAGS - 0046 RAX - , RCX - 7FEBB020, RDX - 0004 RBX - , RSP - 7FF7B760, RBP - 7FF7B760 RSI - 7FF44018, RDI - 7FEBB018 R8 - 00FF, R9 - 00048400, R10 - 00C9 R11 - 0069, R12 - , R13 - R14 - , R15 - DS - 0020, ES - 0020, FS - 0020 GS - 0020, SS - 0020 CR0 - 80010033, CR2 - , CR3 - 7FF6C000 CR4 - 0668, CR8 - DR0 - , DR1 - , DR2 - DR3 - , DR6 - 0FF0, DR7 - 0400 GDTR - 7FF6B000 004F, LDTR - IDTR - 7FF75000 01FF, TR - 0040 FXSAVE_STATE - 7FF7B3C0 Call trace: 0 0x7FF48151 @ 0x7FF46000+0x2151 (0x7FF7B760) in VariableSmm.dll 1 0x7FF54E35 @ 0x7FF46000+0xEE35 (0x7FF7B7D0) in VariableSmm.dll 2 0x7FF5659E @ 0x7FF46000+0x1059E (0x7FF7B800) in VariableSmm.dll 3 0x7FF4BCFE @ 0x7FF46000+0x5CFE (0x7FF7B840) in VariableSmm.dll 4 0x7FFE9BFA @ 0x7FFDB000+0xEBFA (0x7FF7B8A0) in PiSmmCore.dll 5 0x7FFEAAC4 @ 0x7FFDB000+0xFAC4 (0x7FF7B9C0) in PiSmmCore.dll 6 0x7FFEADD1 @ 0x7FFDB000+0xFDD1 (0x7FF7BA20) in PiSmmCore.dll 7 0x7FFE43F8 @ 0x7FFDB000+0x93F8 (0x7FF7BA90) in PiSmmCore.dll 8 0x7FFA8B9A @ 0x7FF9C000+0xCB9A (0x7FF7BD50) in PiSmmCpuDxeSmm.dll 9 0x7FFA9E92 @ 0x7FF9C000+0xDE92 (0x7FF7BDC0) in PiSmmCpuDxeSmm.dll X64 Exception Type - 0E(#PF - Page-Fault) CPU Apic ID - ExceptionData - I:0 R:0 U:0 W:0 P:0 PK:0 S:0 RIP - 7FFA1BBE, CS - 0038, RFLAGS - 00010006 RAX - 7FF89FFC, RCX - 7FF8E149, RDX - RBX - , RSP - 7FF7B1A0, RBP - 7FF7B1E0 RSI - 7FFA9E92, RDI - 7FF9C000 R8 - 0001, R9 - , R10 - R11 - 0069, R12 - , R13 - R14 - , R15 - DS - 0020, ES - 0020, FS - 0020 GS - 0020, SS - 0020 CR0 - 80010033, CR2 - 7FF89FFC, CR3 - 7FF6C000 CR4 - 0668, CR8 - DR0 - , DR1 - , DR2 - DR3 - , DR6 - 0FF0, DR7 - 000
Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
Hi Jiewen, "Yao, Jiewen" <jiewen@intel.com> writes: > I have some more thought on #3 for your consideration. > > Given the situation that we are doing heap guard feature, a *valid* > EIP address might not be enough to guarantee the address is inside of > an *executable* page. OK. > > I am thinking if we need check the non-executable bit (BIT63) as well for > DumpImageModuleNames(). (No need for DumpStacktrace()). > We can add IsLogicalAddressExecutable() on top of > IsLogicalAddressValid(). OK. I can do that. > Also I do not object the idea to add check inside of PeCoffSearchImageBase(). > I am thinking in another way - we can let *caller* to input a validation > function for the PeCoffLib, instead of let PeCoffLib depend on another > library. > > For example: > PeCoffSearchImageBaseEx (Address, ValidateAddressFunc) Looks good to me! Whether or not we're making it into a external library in the future, we should at least get it working and well tested for the stack trace support. Thanks! Paulo >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Yao, >> Jiewen >> Sent: Wednesday, January 17, 2018 8:57 PM >> To: Paulo Alcantara <pa...@paulo.ac>; edk2-devel@lists.01.org >> Cc: Rick Bramley <richard.bram...@hp.com>; Dong, Eric >> <eric.d...@intel.com>; Kimon Berlin <kimon.ber...@hp.com>; Andrew Fish >> <af...@apple.com>; Diego Medaglia <diego.meag...@hp.com>; Laszlo Ersek >> <ler...@redhat.com> >> Subject: Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception >> handling >> >> Thanks Paulo. >> >> The series looks really good. I give it thumb up. :-) >> >> The 8 patches keep updating 4 files, so I squash them when I review. The >> comment below is for the final code, not for a specific patch. >> >> 1) CpuExceptionCommon.c: IsLinearAddressRangeValid(). >> // >> // Check for valid input parameters >> // >> if (LinearAddressStart == 0 || LinearAddressEnd == 0 || >> LinearAddressStart > LinearAddressEnd) { >> return FALSE; >> } >> >> I think LinearAddressStart is a valid case. In BIOS, we do update IVT in 0 >> address >> when CSM is enabled. >> I do not think we need exclude it here. If we enabled ZeroPointer >> protection, it >> can be excluded in page table parsing. >> >> 2) I found below logic appears in 2 functions - DumpImageModuleNames() and >> DumpStacktrace(). Is that possible to merge them? >> We can calculate in DumpImageAndCpuContent() and use Eip as parameter. Just >> in case there is 3rd function need use EIP, it won't miss the calculation. >> (It is a bug fix we did recently.) >> >> // >> // Set current EIP address >> // >> if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) && >> ((SystemContext.SystemContextIa32->ExceptionData & >> IA32_PF_EC_ID) != 0)) { >> // >> // The EIP in SystemContext could not be used >> // if it is page fault with I/D set. >> // >> Eip = *(UINT32 *)(UINTN)SystemContext.SystemContextIa32->Esp; >> } else { >> Eip = SystemContext.SystemContextIa32->Eip; >> } >> >> 3) I am a little surprised on PeCoffSearchImageBase() issue. >> >> We have 4 PeCoffSearchImageBase() call in each arch. >> DumpImageModuleNames() calls twice and DumpStacktrace() calls twice. >> Do you know which specific one triggers the zero address #PF issue? >> >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\Arch >> ExceptionHandler.c(547): ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\Arch >> ExceptionHandler.c(613):ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\Arch >> ExceptionHandler.c(682): ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\Ia32\Arch >> ExceptionHandler.c(741):ImageBase = PeCoffSearchImageBase (Eip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\Arch >> ExceptionHandler.c(540): ImageBase = PeCoffSearchImageBase (Rip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\Arch >> ExceptionHandler.c(613):ImageBase = PeCoffSearchImageBase (Rip); >> >> C:\home\EdkIIGit\edk2\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\Arch >> ExceptionHandl
Re: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
EIP is zero, then stop unwinding the stack > // > if (Eip == 0) { > break; > } > > // > // Search for the respective PE/COFF image based on EIP > // > ImageBase = PeCoffSearchImageBase (Eip); I think so. There is no guarantee that the return address (Eip) will be valid even if we're handling a valid frame pointer. It might get corrupted at some point. Thanks for pointing it out! I'll validate them. > If you can help us do some more investigation on the root-cause and narrow > down the issue, I will appreciate that. > > We can decide how to fix once it is root-caused. Sure. I will. Thanks for the comments! I learnt a lot of with them :-) Paulo > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo >> Alcantara >> Sent: Monday, January 15, 2018 8:23 AM >> To: edk2-devel@lists.01.org >> Cc: Rick Bramley <richard.bram...@hp.com>; Dong, Eric >> <eric.d...@intel.com>; Kimon Berlin <kimon.ber...@hp.com>; Andrew Fish >> <af...@apple.com>; Yao, Jiewen <jiewen@intel.com>; Diego Medaglia >> <diego.meag...@hp.com>; Laszlo Ersek <ler...@redhat.com> >> Subject: [edk2] [RFC v5 0/8] Stack trace support in X64 exception handling >> >> Hi, >> >> This series adds stack trace support during IA32 and X64 CPU exceptions. >> >> Informations like back trace, stack contents and image module names >> (that were part of the call stack) will be dumped out. >> >> The current limitation is that it relies on available frame pointers >> (GCC only) in order to successfully unwind the stack. >> >> Jiewen, >> >> Thank you very much for your time on this. I've applied the changes you >> suggested, as well as tested it on IA32 PAE paging mode - it worked as >> expected. >> >> Other than that, I also tested the stack trace in SMM code by manually >> calling CpuBreakPoint() and then it broke with another exception >> (page fault). I didn't have much time to look into that, but what I've >> observed is that the page fault ocurred during the search of PE/COFF >> image base address (in PeCoffSearchImageBase). The function attempts to >> search for the image base from "Address" through 0, so any of those >> dereferenced addresses triggers the page fault. >> >> Do you know how we could fix that issue? Perhaps introducing a >> AddressValidationLib (as Brian suggested previously) and use it within >> PeCoffSearchImageBase()? >> >> I'd also like to thank Brian & Jeff for all the support! >> >> Thanks >> Paulo >> >> Repo: https://github.com/pcacjr/edk2.git >> Branch: stacktrace_v5 >> >> Cc: Rick Bramley <richard.bram...@hp.com> >> Cc: Kimon Berlin <kimon.ber...@hp.com> >> Cc: Diego Medaglia <diego.meag...@hp.com> >> Cc: Andrew Fish <af...@apple.com> >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Cc: Brian Johnson <brian.john...@hpe.com> >> Cc: Jeff Fan <vanjeff_...@hotmail.com> >> Cc: Jiewen Yao <jiewen@intel.com> >> Cc: Paulo Alcantara <pa...@hp.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> >> --- >> >> v1 -> v2: >> * Add IA32 arch support (GCC toolchain only) >> * Replace hard-coded stack alignment value (16) with >> CPU_STACK_ALIGNMENT. >> * Check for proper stack and frame pointer alignments. >> * Fix initialization of UnwoundStacksCount to 1. >> * Move GetPdbFileName() to common code since it will be used by both >> IA32 and X64 implementations. >> >> v2 -> v3: >> * Fixed wrong assumption about "RIP < ImageBase" to start searching >> for another PE/COFF image. That is, RIP may point to lower and >> higher addresses for any other PE/COFF images. Both IA32 & X64. >> (Thanks Andrew & Jiewen) >> * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) >> >> v3 -> v4: >> * Validate all frame/stack pointer addresses before dereferencing them >> as requested by Brian & Jiewen. >> * Correctly print out IP addresses during the stack traces (by Jeff) >> >> v4 -> v5: >> * Fixed address calculations and improved code as suggested by Jiewen. >> * Fixed parameter validation as suggested by Brian. >> * Tested stack stack wi
[edk2] [RFC v5 4/8] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to validate memory addresses
Introduce IsLinearAddressValid() function that will be used for validating memory addresses that would get dereferenced during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 395 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 16 + 2 files changed, 411 insertions(+) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index 66892320c8..7ac13640de 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -14,6 +14,8 @@ #include "CpuExceptionCommon.h" +#include + // // Error code flag indicating whether or not an error code will be // pushed on the stack if an exception occurs. @@ -59,6 +61,24 @@ CONST CHAR8 *mExceptionNameStr[] = { // GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; +// +// IA32 virtual memory bit definitions +// +#define IA32_PG_P BIT0 +#define IA32_PG_PS BIT7 + +// +// IA32 control register bit definitions +// +#define IA32_CR0_PG BIT31 +#define IA32_CR4_PAE BIT5 +#define IA32_CR0_PE BIT0 + +// +// IA32 CPUID 01h EDX bit definitions +// +#define IA32_CPUID1_EDX_PAE BIT6 + /** Get ASCII format string exception name by exception type. @@ -194,3 +214,378 @@ GetPdbFileName ( } } } + +/** + Check if a linear address is valid by walking the page tables in 4-level + paging mode. + + @param[in] Cr3 CR3 control register. + @param[in] MaxPhyAddrBits MAXPHYADDR bits. + @param[in] LinearAddress Linear address to be checked. +**/ +STATIC +BOOLEAN +Do4LevelPagingModeCheck ( + IN UINTNCr3, + IN UINT8MaxPhyAddrBits, + IN UINTNLinearAddress + ) +{ + UINT64 PhysicalAddressMask; + UINTN IndexMask; + UINTN Index; + UINT64 *Pml4Table; + UINT64 *TableEntry; + UINT64 *PageDirPtrTable; + UINT64 *PageDirTable; + UINT64 *PageTable; + + // + // In 4-level paging mode, linear addresses are 48 bits wide + // + if ((UINT64)LinearAddress > 0xULL) { +return FALSE; + } + + // + // Calculate physical address mask (bits M-1:12) + // + PhysicalAddressMask = (LShiftU64 (1, MaxPhyAddrBits) - 1) & ~0xFFF; + // + // 9 bits for masking page table indexes out of linear addresses + // + IndexMask = 0x1FF; + + // + // Calculate physical address of PML4 table and index of PML4E + // + Pml4Table = (UINT64 *)(UINTN)((UINT64)Cr3 & PhysicalAddressMask); + Index = (UINTN)(RShiftU64 ((UINT64)LinearAddress, 39) & IndexMask); + + // + // Select PML4E + // + TableEntry = [Index]; + + // + // Check if a PDPTE is present + // + if ((*TableEntry & IA32_PG_P) == 0) { +return FALSE; + } + + // + // Calculate physical address of page-directory-pointer table and index of + // PDPTE. + // + PageDirPtrTable = (UINT64 *)(UINTN)(*TableEntry & PhysicalAddressMask); + Index = (UINTN)(RShiftU64 ((UINT64)LinearAddress, 30) & IndexMask); + + // + // Select PDPTE + // + TableEntry = [Index]; + + // + // Check whether a PDPTE or 1GiB page entry is present + // + if ((*TableEntry & IA32_PG_P) == 0) { +return FALSE; + } + + // + // Check if PDPTE maps an 1GiB page + // + if ((*TableEntry & IA32_PG_PS) != 0) { +return TRUE; + } + + // + // Calculate physical address of page directory table and index of PDE + // + PageDirTable = (UINT64 *)(UINTN)(*TableEntry & PhysicalAddressMask); + Index = (UINTN)(RShiftU64 ((UINT64)LinearAddress, 21) & IndexMask); + + // + // Select PDE + // + TableEntry = [Index]; + + // + // Check whether a PDE or a 2MiB page entry is present + // + if ((*TableEntry & IA32_PG_P) == 0) { +return FALSE; + } + + // + // Check if PDE maps a 2MiB page + // + if ((*TableEntry & IA32_PG_PS) != 0) { +return TRUE; + } + + // + // Calculate physical address of page table and index of PTE + // + PageTable = (UINT64 *)(UINTN)(*TableEntry & PhysicalAddressMask); + Index = (UINTN)(RShiftU64 ((UINT64)LinearAddress, 12) & IndexMask); + + // + // Select PTE + // + TableEntry = [Index]; + + // + // Check if PTE maps a 4KiB page + // + if ((*TableEntry & IA32_PG_P) == 0) { +return FALSE; + } + + return TRUE; +} + +/** + Check if a linear address is valid by walking the page tables in 32-bit paging + mode. + + NOTE: Current UEFI implementations do not support IA32 non-PAE paging mode. + + @param[in] Cr3 CR3 con
[edk2] [RFC v5 8/8] UefiCpuPkg/CpuExceptionHandlerLib: Add early check in DumpStackContents
Add an early check in DumpStackContens() to abort in case of no unwound stacks. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 7 +++ UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 7 +++ 2 files changed, 14 insertions(+) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 31fbd4a164..ac3801f704 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -805,6 +805,13 @@ DumpStackContents ( { UINT32 CurrentEsp; + // + // Do nothing in case there wasn't any unwound stack. + // + if (UnwoundStacksCount == 0) { +return; + } + // // Get current stack pointer // diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 4d8c9b0a89..6c3bad01a6 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -418,6 +418,13 @@ DumpStackContents ( UINTN RspAddressStart; UINTN RspAddressEnd; + // + // Do nothing in case there wasn't any unwound stack. + // + if (UnwoundStacksCount == 0) { +return; + } + // // Get current stack pointer // -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v5 7/8] UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges
Introduce a new IsLinearAddressRangeValid() function to validate a given address range and check whether or not it is valid. This function is useful for validating ranges of memory addresses during stack traces in X64. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 40 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 18 + UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 40 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index 7ac13640de..e1dd054259 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -589,3 +589,43 @@ IsLinearAddressValid ( return AddressValid; } + +/** + Check if a linear address range is valid. + + @param[in] Cr0 CR0 control register. + @param[in] Cr3 CR3 control register. + @param[in] Cr4 CR4 control register. + @param[in] LinearAddressStart Linear address start. + @param[in] LinearAddressEndLinear address end. +**/ +BOOLEAN +IsLinearAddressRangeValid ( + IN UINTN Cr0, + IN UINTN Cr3, + IN UINTN Cr4, + IN UINTN LinearAddressStart, + IN UINTN LinearAddressEnd + ) +{ + // + // Check for valid input parameters + // + if (LinearAddressStart == 0 || LinearAddressEnd == 0 || + LinearAddressStart > LinearAddressEnd) { +return FALSE; + } + + // + // Validate all linear addresses within the given range + // + for (LinearAddressStart &= ~(SIZE_4KB - 1); + LinearAddressStart <= LinearAddressEnd; + LinearAddressStart += SIZE_4KB) { +if (!IsLinearAddressValid (Cr0, Cr3, Cr4, LinearAddressStart)) { + return FALSE; +} + } + + return TRUE; +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 1b51034c25..075f668290 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -346,5 +346,23 @@ IsLinearAddressValid ( IN UINTN LinearAddress ); +/** + Check if a linear address range is valid. + + @param[in] Cr0 CR0 control register. + @param[in] Cr3 CR3 control register. + @param[in] Cr4 CR4 control register. + @param[in] LinearAddressStart Linear address start. + @param[in] LinearAddressEndLinear address end. +**/ +BOOLEAN +IsLinearAddressRangeValid ( + IN UINTN Cr0, + IN UINTN Cr3, + IN UINTN Cr4, + IN UINTN LinearAddressStart, + IN UINTN LinearAddressEnd + ); + #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 71d2d2f5d4..4d8c9b0a89 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -415,6 +415,8 @@ DumpStackContents ( UINTN Cr0; UINTN Cr3; UINTN Cr4; + UINTN RspAddressStart; + UINTN RspAddressEnd; // // Get current stack pointer @@ -436,21 +438,29 @@ DumpStackContents ( Cr3 = SystemContext.SystemContextX64->Cr3; Cr4 = SystemContext.SystemContextX64->Cr4; + // + // Calculate address range of the stack pointers + // + RspAddressStart = (UINTN)CurrentRsp; + RspAddressEnd = +RspAddressStart + (UINTN)UnwoundStacksCount * CPU_STACK_ALIGNMENT; + + // + // Validate address range of stack pointers + // + if (!IsLinearAddressRangeValid (Cr0, Cr3, Cr4, RspAddressStart, + RspAddressEnd)) { +InternalPrintMessage ("%a: attempted to dereference an invalid stack " + "pointer at 0x%016lx - 0x%016lx\n", __FUNCTION__, + RspAddressStart, RspAddressEnd); +return; + } + // // Dump out stack contents // InternalPrintMessage ("\nStack dump:\n"); while (UnwoundStacksCount-- > 0) { -// -// Check for a valid stack pointer address -// -if (!IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)CurrentRsp) || -!IsLinearAddressValid (Cr0, Cr3, Cr4, (UINTN)CurrentRsp + 8)) { - InternalPrintMessage ("%a: attempted to dereference an inva
[edk2] [RFC v5 0/8] Stack trace support in X64 exception handling
Hi, This series adds stack trace support during IA32 and X64 CPU exceptions. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. The current limitation is that it relies on available frame pointers (GCC only) in order to successfully unwind the stack. Jiewen, Thank you very much for your time on this. I've applied the changes you suggested, as well as tested it on IA32 PAE paging mode - it worked as expected. Other than that, I also tested the stack trace in SMM code by manually calling CpuBreakPoint() and then it broke with another exception (page fault). I didn't have much time to look into that, but what I've observed is that the page fault ocurred during the search of PE/COFF image base address (in PeCoffSearchImageBase). The function attempts to search for the image base from "Address" through 0, so any of those dereferenced addresses triggers the page fault. Do you know how we could fix that issue? Perhaps introducing a AddressValidationLib (as Brian suggested previously) and use it within PeCoffSearchImageBase()? I'd also like to thank Brian & Jeff for all the support! Thanks Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v5 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Kimon Berlin <kimon.ber...@hp.com> Cc: Diego Medaglia <diego.meag...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Brian Johnson <brian.john...@hpe.com> Cc: Jeff Fan <vanjeff_...@hotmail.com> Cc: Jiewen Yao <jiewen@intel.com> Cc: Paulo Alcantara <pa...@hp.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. v2 -> v3: * Fixed wrong assumption about "RIP < ImageBase" to start searching for another PE/COFF image. That is, RIP may point to lower and higher addresses for any other PE/COFF images. Both IA32 & X64. (Thanks Andrew & Jiewen) * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) v3 -> v4: * Validate all frame/stack pointer addresses before dereferencing them as requested by Brian & Jiewen. * Correctly print out IP addresses during the stack traces (by Jeff) v4 -> v5: * Fixed address calculations and improved code as suggested by Jiewen. * Fixed parameter validation as suggested by Brian. * Tested stack stack with IA32 PAE paging mode. Paulo Alcantara (8): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Add helper to validate memory addresses UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses UefiCpuPkg/CpuExceptionHandlerLib: Validate memory address ranges UefiCpuPkg/CpuExceptionHandlerLib: Add early check in DumpStackContents UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 537 ++-- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 59 ++- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 483 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 426 +++- 4 files changed, 1435 insertions(+), 70 deletions(-) -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v5 6/8] UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses
Remove the supurious '- 1' when calculating the IP addresses during the stack traces. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Jeff Fan <vanjeff_...@hotmail.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 2 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 3b92512b92..31fbd4a164 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -590,7 +590,7 @@ DumpStacktrace ( *UnwoundStacksCount - 1, Eip, ImageBase, - Eip - ImageBase - 1, + Eip - ImageBase, Ebp, PdbFileName ); diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index c81f4c00eb..71d2d2f5d4 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -739,7 +739,7 @@ DumpStacktrace ( *UnwoundStacksCount - 1, Rip, ImageBase, - Rip - ImageBase - 1, + Rip - ImageBase, Rbp, PdbFileName ); -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v5 1/8] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 401 +++- 1 file changed, 393 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 56180f4c17..4db9f6465e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -399,20 +404,281 @@ DumpCpuContext ( } /** - Display CPU information. + Get absolute path and file name of PDB file in PE/COFF image. - @param ExceptionType Exception type. - @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. **/ +STATIC VOID -DumpImageAndCpuContent ( +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned stack pointer. \n"); +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + +// +// Point to next stack +// +CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( IN EFI_EXCEPTION_TYPE ExceptionType, IN EFI_SYSTEM_CONTEXT SystemContext ) { - DumpCpuContext (ExceptionType, SystemContext); + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID*EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP address + // + if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) && + ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0)) { +// +// The RIP in SystemContext could not be used +// if it is page fault with I/D set. +// +Rip = *(UINT64 *)(UINTN)SystemContext.SystemContextX64->Rsp; + } else { +Rip = SystemContext.SystemContextX64->Rip; + } + + // + // Set current frame pointer address + // + Rbp = SystemContext.SystemContextX64->Rbp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base addr
[edk2] [RFC v5 3/8] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support
This patch adds stack trace support during a IA32 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 42 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 11 - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 335 +++- 3 files changed, 327 insertions(+), 61 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index d9abbd772d..66892320c8 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -109,48 +109,6 @@ InternalPrintMessage ( SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); } -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ) -{ - EFI_STATUS Status; - UINTNPe32Data; - VOID *PdbPointer; - VOID *EntryPoint; - - Pe32Data = PeCoffSearchImageBase (CurrentEip); - if (Pe32Data == 0) { -InternalPrintMessage (" Can't find image information. \n"); - } else { -// -// Find Image Base entry point -// -Status = PeCoffLoaderGetEntryPoint ((VOID *) Pe32Data, ); -if (EFI_ERROR (Status)) { - EntryPoint = NULL; -} -InternalPrintMessage (" Find image based on IP(0x%x) ", CurrentEip); -PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); -if (PdbPointer != NULL) { - InternalPrintMessage ("%a", PdbPointer); -} else { - InternalPrintMessage ("(No PDB) " ); -} -InternalPrintMessage ( - " (ImageBase=%016lp, EntryPoint=%016p) \n", - (VOID *) Pe32Data, - EntryPoint - ); - } -} - /** Read and save reserved vector information diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 64c7094513..ec46c2d9d3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -130,17 +130,6 @@ InternalPrintMessage ( ... ); -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ); - /** Display CPU information. diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 04f2ab593c..c5d6ea0939 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -399,20 +399,156 @@ DumpCpuContext ( } /** - Display CPU information. + Dump stack trace. - @param ExceptionType Exception type. - @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] ExceptionType Exception type. + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. **/ +STATIC VOID -DumpImageAndCpuContent ( +DumpStacktrace ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + if ((ExceptionType == EXCEPT_IA32_PAGE_FAULT) && + ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0)) { +// +// The EIP in SystemContext could not be used +// if it is page fault with I/D set. +// +Eip = *(UINT32 *)(UINTN)SystemContext.SystemContextIa32->Esp; + } else { +Eip = SystemContext.SystemContextIa32->Eip; + } + + // + // Set current frame pointer address + // + Ebp = SystemContext.SystemContextIa32->Ebp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Ebp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase = PeCoffSearchImageBase (Eip); + if (ImageBase == 0) { +InternalPrintMessage (
[edk2] [RFC v5 5/8] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers
Validate all possible memory dereferences during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 149 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 75 +- 2 files changed, 216 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index c5d6ea0939..3b92512b92 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// IA32 Segment Selector bit definitions +// +#define IA32_SEGSEL_TI BIT2 + /** Return address map of exception handler template so that C code can generate exception tables. @@ -398,6 +403,97 @@ DumpCpuContext ( ); } +/** + Check if a logical address is valid. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] SegmentSelectorSegment selector. + @param[in] Offset Offset or logical address. +**/ +STATIC +BOOLEAN +IsLogicalAddressValid ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT16 SegmentSelector, + IN UINTNOffset + ) +{ + IA32_SEGMENT_DESCRIPTOR *SegmentDescriptor; + UINT32 SegDescBase; + UINT32 SegDescLimit; + UINT64 SegDescLimitInBytes; + + // + // Check for valid input parameters + // + if (SegmentSelector == 0 || Offset == 0) { +return FALSE; + } + + // + // Look for a segment descriptor in a GDT or LDT table depending on TI + // (Table Indicator) bit in segment selector. + // + if ((SegmentSelector & IA32_SEGSEL_TI) == 0) { +// +// Get segment descriptor from GDT table +// +SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( +(UINTN)SystemContext.SystemContextIa32->Gdtr[0] + +(SegmentSelector & ~7) +); + } else { +// +// Get segment descriptor from LDT table +// +SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( +(UINTN)SystemContext.SystemContextIa32->Ldtr + +(SegmentSelector & ~7) +); + } + + // + // Get segment descriptor's base address + // + SegDescBase = SegmentDescriptor->Bits.BaseLow | +(SegmentDescriptor->Bits.BaseMid << 16) | +(SegmentDescriptor->Bits.BaseHigh << 24); + + // + // Get segment descriptor's limit + // + SegDescLimit = SegmentDescriptor->Bits.LimitLow | +(SegmentDescriptor->Bits.LimitHigh << 16); + + // + // Calculate segment descriptor's limit in bytes + // + if (SegmentDescriptor->Bits.G == 1) { +SegDescLimitInBytes = (UINT64)SegDescLimit * SIZE_4KB + (SIZE_4KB - 1); + } else { +SegDescLimitInBytes = SegDescLimit; + } + + // + // Make sure to not access beyond a segment limit boundary + // + if ((UINT64)Offset + SegDescBase > SegDescLimitInBytes) { +return FALSE; + } + + // + // Check if the translated logical address (or linear address) is valid + // + return IsLinearAddressValid ( +SystemContext.SystemContextIa32->Cr0, +SystemContext.SystemContextIa32->Cr3, +SystemContext.SystemContextIa32->Cr4, +Offset + SegDescBase +); +} + /** Dump stack trace. @@ -470,6 +566,20 @@ DumpStacktrace ( InternalPrintMessage ("\nCall trace:\n"); for (;;) { +// +// Check for valid frame pointer +// +if (!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp + 4) || +!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp)) { + InternalPrintMessage ("%a: attempted to dereference an invalid frame " +"pointer at 0x%08x\n", __FUNCTION__, Ebp); + break; +} + // // Print stack frame in the following format: // @@ -610,6 +720,16 @@ DumpImageModuleNames ( // Walk through call stack and find next module names // for (;;) { +if (!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp) || +!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +
[edk2] [RFC v5 2/8] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName()
This function will be used by both IA32 and X64 exception handling in order to print out image module names during stack unwinding. Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 60 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 14 + UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 59 --- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index 01b0610364..d9abbd772d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -54,6 +54,11 @@ CONST CHAR8 *mExceptionNameStr[] = { #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *)) +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Get ASCII format string exception name by exception type. @@ -177,4 +182,57 @@ ReadAndVerifyVectorInfo ( VectorInfo ++; } return EFI_SUCCESS; -} \ No newline at end of file +} + +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index e10d9379d5..64c7094513 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -327,5 +327,19 @@ AsmGetTssTemplateMap ( OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap ); +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ); + #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 4db9f6465e..523dce95c9 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,11 +14,6 @@ #include "CpuExceptionCommon.h" -// -// Unknown PDB file name -// -GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; - /** Return address map of exception handler template so that C code can generate exception tables. @@ -403,60 +398,6 @@ DumpCpuContext ( ); } -/** - Get absolute path and file name of PDB file in PE/COFF image. - - @param[in] ImageBaseBase address of PE/COFF image. - @param[out] PdbAbsoluteFilePath Absolute path of PDB file. - @param[out] PdbFileName File name of PDB file. -**/ -STATIC -VOID -GetPdbFileName ( - IN UINTNImageBase, - OUT CHAR8**PdbAbsoluteFilePath, - OUT CHAR8**PdbFileName - ) -{ - VOID *PdbPointer; - CHAR8 *Str; - - // - // Get PDB file name from PE/COFF image - // - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); - if (PdbPointer == NULL) { -// -// No PDB file name found. Set it to an unknown file name. -// -*PdbFileName = (C
Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
"Yao, Jiewen" <jiewen@intel.com> writes: Hi Jiewen, > For 7), you are right that we disable IA32 paging by default. > However, we do support IA32 PAE in DxeIpl. Please refer to > MdeModulePkg\Core\DxeIplPeim\Ia32\DxeLoadFunc.c > == > PageTables = 0; > BuildPageTablesIa32Pae = (BOOLEAN) (PcdGetBool (PcdSetNxForStack) && > IsIa32PaeSupport () && IsExecuteDisableBitAvailable ()); > if (BuildPageTablesIa32Pae) { > PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE); > EnableExecuteDisableBit (); > } > == > > Please notice that we only support IA32 PAE, we do not support IA32 > non-PAE mode so far. (no matter PSE is ON/OFF) Cool! I didn't know about it. > > So, I suggest: > 7.1) Please validate IA32 PAE mode. (You can enable PcdSetNxForStack) I will. Thanks! > 7.2) If we cannot validate the IA32 non-PAE code, please remove > them. You can just print "IA32 non-PAE - UNSUPPORTED" and return > invalid address. Then it can save our development time, review time, > and validation time. The key is that we only want to check in the > validated code. You're right. I'll keep only the code that we were able to validate its implementation (e.g. 4-level & 32-bit PAE). Thanks! Paulo >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo >> Alcantara >> Sent: Thursday, January 4, 2018 9:30 PM >> To: Yao, Jiewen <jiewen@intel.com>; Yao, Jiewen <jiewen@intel.com>; >> edk2-devel@lists.01.org >> Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> Subject: Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add >> helper to valid memory addresses >> >> "Yao, Jiewen" <jiewen@intel.com> writes: >> >> > 5) For CR4, please use meaning definition for BIT4/BIT5. >> > if ((Cr4 & BIT4) != 0 && (*PageDirEntry & BIT7) != 0) { >> > if (((Cr4 & BIT5) != 0 && (UINT64)LinearAddress > 0xFULL) || >> >> OK. >> >> > >> > 6) For IA32 PAE/PSE calculation, same comment for 3 and 4. >> >> OK. >> >> > >> > 7) Last but not least important, would you please share the information on >> how do you validate the 32bit PAE/PSE/normal 4K page table? >> >> Since on IA32 we use 32-bit protected flat model and paging disabled >> (OK?), I wasn't able to validate the paging modes other than 4-level >> paging mode in X64. The memory validation code I wrote is heavily based >> upon what I read from Intel SDM Vol 3A manual. >> >> If you do have any idea on how to validate it -- whether it's a PoC or >> test code -- please let me know, and then I validate it. >> >> Thanks again for your review! >> >> Paulo >> >> > >> > Thank you >> > Yao Jiewen >> > >> >> -Original Message- >> >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of >> Yao, >> >> Jiewen >> >> Sent: Thursday, January 4, 2018 9:36 AM >> >> To: Paulo Alcantara <pa...@paulo.ac>; edk2-devel@lists.01.org >> >> Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> >> Subject: Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add >> >> helper to valid memory addresses >> >> >> >> Some suggestion: >> >> >> >> 1) I am not sure if it is proper to use ASSERT in an exception handler, >> >> because >> we >> >> know something is wrong. >> >> >> >> ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); >> >> >> >> I suggest we just do the check, and return FALSE, if the prerequisite is >> >> not >> >> satisfied. >> >> >> >> 2) Can we use meaningful definition for BIT0, BIT7? >> >> >> >> if ((*Pml4TableEntry & BIT0) == 0) { >> >> if ((*PageDirPtrTableEntry & BIT7) != 0) { >> >> >> >> 3) I am not sure if I understand below code. >> >> >> >> PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> >> PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << >> 12); >> >> PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) - >> 1) >> >&
Re: [edk2] [RFC v4 0/6] Stack trace support in X64 exception handling
"Yao, Jiewen" <jiewen@intel.com> writes: Hi Jiewen, > I tried to apply the patch series to latest code, but fail with below message. > > Have you rebased to latest code? Hrm - I thought I did before sending out v4. Sorry for that. I'll make sure to rebase it against latest master before sending out v5. Thanks Paulo > > === > git.exe am --3way --ignore-space-change --keep-cr > "C:\home\EdkIIGit\edk2\[edk2]-[RFC-v4-1-6]-UefiCpuPkg-CpuExceptionHandlerLib-X64-Add-stack-trace-support.patch" > Applying: UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support > Using index info to reconstruct a base tree... > M UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c > Falling back to patching base and 3-way merge... > Auto-merging > UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c > CONFLICT (content): Merge conflict in > UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c > Patch failed at 0001 UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace > support > The copy of the patch that failed is found in: .git/rebase-apply/patch > When you have resolved this problem, run "git am --continue". > If you prefer to skip this patch, run "git am --skip" instead. > To restore the original branch and stop patching, run "git am --abort". > > .git/rebase-apply/patch:13: trailing whitespace. > // > .git/rebase-apply/patch:14: trailing whitespace. > // Unknown PDB file name > .git/rebase-apply/patch:15: trailing whitespace. > // > .git/rebase-apply/patch:16: trailing whitespace. > GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; > .git/rebase-apply/patch:17: trailing whitespace. > > warning: squelched 369 whitespace errors > warning: 374 lines add whitespace errors. > error: Failed to merge in the changes. > > Fail > = > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo >> Alcantara >> Sent: Friday, December 29, 2017 11:49 AM >> To: edk2-devel@lists.01.org >> Cc: Rick Bramley <richard.bram...@hp.com>; Dong, Eric >> <eric.d...@intel.com>; Andrew Fish <af...@apple.com>; Yao, Jiewen >> <jiewen@intel.com>; Laszlo Ersek <ler...@redhat.com> >> Subject: [edk2] [RFC v4 0/6] Stack trace support in X64 exception handling >> >> Hi, >> >> This series adds stack trace support during IA32 and X64 CPU exceptions. >> >> Informations like back trace, stack contents and image module names >> (that were part of the call stack) will be dumped out. >> >> The current limitation is that it relies on available frame pointers >> (GCC only) in order to successfully unwind the stack. >> >> (Sorry for the very long delay - I was very busy working on something >> else and then went to vacations) >> >> Jiewen, >> >> I have tested it with VS2015x86 and the stack trace just hanged when >> printing out the first EIP (that is, no frame pointer at all). >> >> Thanks! >> Paulo >> >> Repo: https://github.com/pcacjr/edk2.git >> Branch: stacktrace_v4 >> >> Cc: Rick Bramley <richard.bram...@hp.com> >> Cc: Andrew Fish <af...@apple.com> >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Cc: Brian Johnson <brian.john...@hpe.com> >> Cc: Jeff Fan <vanjeff_...@hotmail.com> >> Cc: Jiewen Yao <jiewen@intel.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> >> --- >> >> v1 -> v2: >> * Add IA32 arch support (GCC toolchain only) >> * Replace hard-coded stack alignment value (16) with >> CPU_STACK_ALIGNMENT. >> * Check for proper stack and frame pointer alignments. >> * Fix initialization of UnwoundStacksCount to 1. >> * Move GetPdbFileName() to common code since it will be used by both >> IA32 and X64 implementations. >> >> v2 -> v3: >> * Fixed wrong assumption about "RIP < ImageBase" to start searching >> for another PE/COFF image. That is, RIP may point to lower and >> higher addresses for any other PE/COFF images. Both IA32 & X64. >> (Thanks Andrew & Jiewen) >> * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) >> >> v3 -> v4: >> * Validate all frame/stack pointer addresses before dereferencing them >> as
Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
"Yao, Jiewen" <jiewen@intel.com> writes: > 5) For CR4, please use meaning definition for BIT4/BIT5. > if ((Cr4 & BIT4) != 0 && (*PageDirEntry & BIT7) != 0) { > if (((Cr4 & BIT5) != 0 && (UINT64)LinearAddress > 0xFULL) || OK. > > 6) For IA32 PAE/PSE calculation, same comment for 3 and 4. OK. > > 7) Last but not least important, would you please share the information on > how do you validate the 32bit PAE/PSE/normal 4K page table? Since on IA32 we use 32-bit protected flat model and paging disabled (OK?), I wasn't able to validate the paging modes other than 4-level paging mode in X64. The memory validation code I wrote is heavily based upon what I read from Intel SDM Vol 3A manual. If you do have any idea on how to validate it -- whether it's a PoC or test code -- please let me know, and then I validate it. Thanks again for your review! Paulo > > Thank you > Yao Jiewen > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Yao, >> Jiewen >> Sent: Thursday, January 4, 2018 9:36 AM >> To: Paulo Alcantara <pa...@paulo.ac>; edk2-devel@lists.01.org >> Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> Subject: Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add >> helper to valid memory addresses >> >> Some suggestion: >> >> 1) I am not sure if it is proper to use ASSERT in an exception handler, >> because we >> know something is wrong. >> >> ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); >> >> I suggest we just do the check, and return FALSE, if the prerequisite is not >> satisfied. >> >> 2) Can we use meaningful definition for BIT0, BIT7? >> >> if ((*Pml4TableEntry & BIT0) == 0) { >> if ((*PageDirPtrTableEntry & BIT7) != 0) { >> >> 3) I am not sure if I understand below code. >> >> PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) - 1) >> << 12); >> PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> >> If MaxPhyAddrBits is 48, you will get "Cr3 & 0x0000". Is that >> what >> you want? I think we need "Cr3 & 0xF000" >> Should it be: PhysicalAddress = (UINT64)Cr3 & ((1ULL << MaxPhyAddrBits) - 1) >> & >> (~0xFFF); >> >> 4) Can we use a more readable way to below? Personally, I do not suggest "<< >> 3", >> which is just the index calculation. >> >> PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; >> Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; >> PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); >> >> For example: >> PhysicalAddress = (UINT64)Cr3 & ((1ULL << MaxPhyAddrBits) - 1) & (~0xFFF); >> Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; >> Index= (UINTN)(((UINT64)LinearAddress >> 39) & 0x1FF); >> PhysicalAddress = Pml4TableEntry[Index] & ((1ULL << MaxPhyAddrBits) - 1) & >> (~0xFFF); >> >> >> >> Thank you >> Yao Jiewen >> >> >> > -Original Message- >> > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of >> Paulo >> > Alcantara >> > Sent: Friday, December 29, 2017 12:40 PM >> > To: edk2-devel@lists.01.org >> > Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> > Subject: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper >> to >> > valid memory addresses >> > >> > Introduce IsLinearAddressValid() function that will be used for >> > validating memory addresses that would get dereferenced during stack >> > traces in IA32 and X64 CPU exceptions. >> > >> > Contributed-under: TianoCore Contribution Agreement 1.1 >> > Cc: Eric Dong <eric.d...@intel.com> >> > Cc: Laszlo Ersek <ler...@redhat.com> >> > Requested-by: Brian Johnson <brian.john...@hpe.com> >> > Requested-by: Jiewen Yao <jiewen@intel.com> >> > Si
Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
"Yao, Jiewen" <jiewen@intel.com> writes: Hi Jiewen, > Some suggestion: > > 1) I am not sure if it is proper to use ASSERT in an exception handler, > because we know something is wrong. > > ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); > > I suggest we just do the check, and return FALSE, if the prerequisite is not > satisfied. OK. > > 2) Can we use meaningful definition for BIT0, BIT7? > > if ((*Pml4TableEntry & BIT0) == 0) { > if ((*PageDirPtrTableEntry & BIT7) != 0) { Sure. Sorry for missing that. > > 3) I am not sure if I understand below code. > > PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); > PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); > PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) - 1) > << 12); > PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); > > If MaxPhyAddrBits is 48, you will get "Cr3 & 0x0000". Is that > what you want? I think we need "Cr3 & 0xF000" > Should it be: PhysicalAddress = (UINT64)Cr3 & ((1ULL << MaxPhyAddrBits) - 1) > & (~0xFFF); Yes, it should. I've just re-checked the Intel SDM Vol 3A and your calculation is correct. Thanks! I'll fix that up in next series. > > 4) Can we use a more readable way to below? Personally, I do not suggest "<< > 3", which is just the index calculation. > > PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); > PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; > Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; > PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); > > For example: > PhysicalAddress = (UINT64)Cr3 & ((1ULL << MaxPhyAddrBits) - 1) & (~0xFFF); > Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; > Index= (UINTN)(((UINT64)LinearAddress >> 39) & 0x1FF); > PhysicalAddress = Pml4TableEntry[Index] & ((1ULL << MaxPhyAddrBits) - 1) & > (~0xFFF); Sure. This way is much clearer, indeed. Thank you very much for the effort on reviewing this! Paulo >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo >> Alcantara >> Sent: Friday, December 29, 2017 12:40 PM >> To: edk2-devel@lists.01.org >> Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> Subject: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to >> valid memory addresses >> >> Introduce IsLinearAddressValid() function that will be used for >> validating memory addresses that would get dereferenced during stack >> traces in IA32 and X64 CPU exceptions. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Requested-by: Brian Johnson <brian.john...@hpe.com> >> Requested-by: Jiewen Yao <jiewen@intel.com> >> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> >> --- >> UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 382 >> >> UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 16 + >> 2 files changed, 398 insertions(+) >> >> diff --git >> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c >> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c >> index 867c5c01d6..52b3eb1463 100644 >> --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c >> +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c >> @@ -14,6 +14,9 @@ >> >> #include "CpuExceptionCommon.h" >> >> +#include >> +#include >> + >> // >> // Error code flag indicating whether or not an error code will be >> // pushed on the stack if an exception occurs. >> @@ -194,3 +197,382 @@ GetPdbFileName ( >> } >>} >> } >> + >> +/** >> + Check if a linear address is valid by walking the page tables in 4-level >> + paging mode. >> + >> + @param[in] Cr3 CR3 control register. >> + @param[in] MaxPhyAddrBits MAXPHYADDRBITS bits. >> + @param[in] LinearAddress Linear address to be checked. >> +**/ >> +STATIC >> +BOOLEAN >> +Do4LevelPagingModeCheck ( >> + IN UINTNCr3, >> + IN U
Re: [edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
"Brian J. Johnson" <brian.john...@hpe.com> writes: Hi Brian, > On 12/28/2017 10:39 PM, Paulo Alcantara wrote: >> + // >> + // Check if paging is disabled >> + // >> + if ((Cr0 & BIT31) == 0) { >> +// >> +// If CR4.PAE bit is set, then the linear (or physical) address supports >> +// only up to 36 bits. >> +// >> +if (((Cr4 & BIT5) != 0 && (UINT64)LinearAddress > 0xFULL) || >> +LinearAddress > 0x) { >> + return FALSE; >> +} >> + >> +return TRUE; >> + } > > Paulo, > > The logic there doesn't look quite right: if LinearAddress is between > 2^32 and 2^36-1, this code will always return FALSE, even if CR4.PAE is > set. Shouldn't it be: > > if ((UINT64)LinearAddress > 0xFULL || > ((Cr4 & BIT5) == 0 && LinearAddress > 0x)) { > return FALSE; > } You're right. The check is bogus and I'll fix it up in the next version. > > (I haven't examined all the code in detail, I just happened to notice > this issue.) No problem. Your comments are very appreciable. > This bug should get fixed before pushing this series. I also have some > more general design questions, which shouldn't hold up pushing the > series, but I think merit some discussion: > > This is great code for validating addresses in general, especially when > guard pages are in use for NULL pointers, stack overflow, etc. Thanks > for adding it! But for [er]sp and [er]bp validation, don't you really > just want to know if the address is in the expected stack range? Maybe > the code which sets up the stack could communicate the valid range to > CpuExceptionHandlerLib somehow. It could use special debug register > values like > SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLib.c > does. Or perhaps it could use dynamic PCDs (although I don't know that > it's a good idea to go looking up PCDs in an exception handler.) Or > maybe there's a more straightforward way It would have to take AP > stacks into account, and probably SetJump/LongJump as well. That may or > may not be simpler than the current code I'm not quite sure if I understood you correctly when you say that I should be checking whether the address is in the expected range, but using the debug registers to save call stack information seems like a good idea, although it doesn't seem to be that simple as you mentioned. > > More generally, I'd like to see some sort of platform-specific callout > to further validate addresses. Not all mapped addresses, or addresses > up to the architectural limit, are safe to access. For instance, reads > to SMRAM outside of SMM will cause exceptions. Also, we wouldn't want > to go backtracing through MMIO or MMCFG space: reads there could > potentially have side effects on the hardware. Yes - we should ensure that those regions are not accessed during the stacktrace, as well as test this implementation a lot more. > > The rules can also vary at different points in boot. For example, > before memory is initialized, Intel Xeon processors generally execute > 32-bit code in cache-as-RAM mode, where the caches are jury-rigged to > operate as temporary storage while the memory setup code is running. In > CAR mode, only a few address ranges can be accessed without causing > machine checks: the cache-as-RAM range containing the stack, heap, and > HOB list, the architectural firmware range below 4G, and a few specific > MMCFG and MMIO ranges. Really great info. Thanks. We should take that into account as well. > > So I'd like to suggest that you define an AddressValidationLib library > class, which provides a routine which takes an address (or an address > range?) and an indication of the intended use (memory read, memory > write, execute/disassemble code, stack dump, IO, ...), and returns a > value specifying if the access is: > - safe (IsLinearAddressValid() should return TRUE) > - unsafe (IsLinearAddressValid() should return FALSE) > - unknown (IsLinearAddressValid() should perform its other tests) > > You can supply a NULL instance which always returns "unknown" for > platforms which don't want to perform their own validation. Great idea! I can do that for sure, but first of all, I'd like to make sure the memory validation code is working correctly for IA32 and X64 platforms before introducing the AddressValidationLib library. Thank you very much for the review and comments! Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] 答复: [RFC v4 1/6] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Hi Jeff, On 1/3/2018 6:53 AM, Fan Jeff wrote: Paulo, I did not receive your #0 patch. So, I reply #1 here. Your serial of patches should work for IA32/X64 GCC and IA32 MSFT. I suggest you could push this serial of patches as soon as pass UefiCpuPkg owner/reviewers’ review and validation, OK - That would be really appreciable if you could test it with IA32 MSFT toolchain and see if the stacktrace is printed out correctly when passing the '/Oy-' compile option. And then I could send my x64 MSFT support later. Cool. Thanks Paulo *From:* edk2-devel <edk2-devel-boun...@lists.01.org> on behalf of Paulo Alcantara <pa...@paulo.ac> *Sent:* Friday, December 29, 2017 12:39:34 PM *To:* edk2-devel@lists.01.org *Cc:* Laszlo Ersek; Eric Dong *Subject:* [edk2] [RFC v4 1/6] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 376 +++- 1 file changed, 374 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 1dcf4277de..19bfaa329a 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -398,6 +403,357 @@ DumpCpuContext ( ); } +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBase Base address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTN ImageBase, + OUT CHAR8 **PdbAbsoluteFilePath, + OUT CHAR8 **PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { + // + // No PDB file name found. Set it to an unknown file name. + // + *PdbFileName = (CHAR8 *)mUnknownPdbFileName; + if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; + } + } else { + // + // Get file name portion out of PDB file in PE/COFF image + // + Str = (CHAR8 *)((UINTN)PdbPointer + + AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); + for (; *Str != '/' && *Str != '\\'; Str--) { + ; + } + + // + // Set PDB file name (also skip trailing path separator: '/' or '\\') + // + *PdbFileName = Str + 1; + + if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; + } + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTN UnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { + InternalPrintMessage (" Unaligned stack pointer. \n"); + return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { + InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + + // + // Point to next stack + // + CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID *EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP address + // + Rip = SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // +
Re: [edk2] 答复: [RFC v4 5/6] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers
On 1/3/2018 6:45 AM, Fan Jeff wrote: Paulo, + if (!IsLogicalAddressValid (SystemContext, + SystemContext.SystemContextIa32->Ss, + (UINTN)Ebp) || + !IsLogicalAddressValid (SystemContext, + SystemContext.SystemContextIa32->Ss, + (UINTN)Ebp + 4)) { I don’t understand why you check both ebp and ebp+4, I think it’s enough to only check EBP (saved stack pointer address) Isn't it possible that EBP + 4 might potentially point to another page frame? If not, then I will drop it out in v5. Thanks Paulo Jeff *发件人: *Paulo Alcantara <mailto:pa...@paulo.ac> *发送时间: *2017年12月29日12:41 *收件人: *edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> *抄送: *Laszlo Ersek <mailto:ler...@redhat.com>; Eric Dong <mailto:eric.d...@intel.com> *主题: *[edk2] [RFC v4 5/6] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers Validate all possible memory dereferences during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 143 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 75 +- 2 files changed, 210 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 25e02fbbc1..9b52d4f6d2 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -398,6 +398,96 @@ DumpCpuContext ( ); } +/** + Check if a logical address is valid. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] SegmentSelector Segment selector. + @param[in] Offset Offset or logical address. +**/ +STATIC +BOOLEAN +IsLogicalAddressValid ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT16 SegmentSelector, + IN UINTN Offset + ) +{ + IA32_SEGMENT_DESCRIPTOR *SegmentDescriptor; + UINT32 SegDescBase; + UINT32 SegDescLimit; + UINTN SegDescLimitInBytes; + + // + // Check for valid input parameters + // + if (SegmentSelector == 0 || Offset == 0) { + return FALSE; + } + + // + // Check whether to look for a segment descriptor in GDT or LDT table + // + if ((SegmentSelector & BIT2) == 0) { + // + // Get segment descriptor from GDT table + // + SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( + (UINTN)SystemContext.SystemContextIa32->Gdtr[0] + + ((SegmentSelector >> 3) * 8) + ); + } else { + // + // Get segment descriptor from LDT table + // + SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( + (UINTN)SystemContext.SystemContextIa32->Ldtr + + ((SegmentSelector >> 3) * 8) + ); + } + + // + // Get segment descriptor's base address + // + SegDescBase = SegmentDescriptor->Bits.BaseLow | + (SegmentDescriptor->Bits.BaseMid << 16) | + (SegmentDescriptor->Bits.BaseHigh << 24); + + // + // Get segment descriptor's limit + // + SegDescLimit = SegmentDescriptor->Bits.LimitLow | + (SegmentDescriptor->Bits.LimitHigh << 16); + + // + // Calculate segment descriptor's limit in bytes + // + if (SegmentDescriptor->Bits.G == 1) { + SegDescLimitInBytes = (UINTN)SegDescLimit * SIZE_4KB; + } else { + SegDescLimitInBytes = SegDescLimit; + } + + // + // Make sure to not access beyond a segment limit boundary + // + if (Offset + SegDescBase > SegDescLimitInBytes) { + return FALSE; + } + + // + // Check if the translated logical address (or linear address) is valid + // + return IsLinearAddressValid ( + SystemContext.SystemContextIa32->Cr0, + SystemContext.SystemContextIa32->Cr3, + SystemContext.SystemContextIa32->Cr4, + Offset + SegDescBase + ); +} + /** Dump stack trace. @@ -459,6 +549,20 @@ DumpStackTrace ( InternalPrintMessage ("\nCall trace:\n"); for (;;) { + // + // Check for valid frame pointer + // + if (!IsLogicalAddressValid (SystemContext, + SystemContext.SystemContextIa32->Ss, + (UINTN)Ebp + 4) || + !IsLogicalAddressValid (SystemContext, + SystemContext.SystemContextIa32->Ss, + (UINTN)Ebp)) { +
Re: [edk2] 答复: [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
Hi Jeff, On 1/3/2018 6:42 AM, Fan Jeff wrote: Paul, + // + // Calculate physical address of PML4E + // + PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; + Should not pass VS build, instead you could use LShiftU64/RShiftU64 to do 64bit shift operation as below: PhysicalAddress = (UINT64)Cr3 & LShiftU64 (LShiftU64 (1, MaxPhyAddrBits) - 1, 12); PhysicalAddress |= LShiftU64 (RShiftU64((UINT64)LinearAddress, 39) & 0x1FF), 3); OK - I'll fix them up and then build-test it with IA32/X64 MSFT toolchain. Thanks Paulo Jeff *发件人: *Paulo Alcantara <mailto:pa...@paulo.ac> *发送时间: *2017年12月29日12:41 *收件人: *edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> *抄送: *Laszlo Ersek <mailto:ler...@redhat.com>; Eric Dong <mailto:eric.d...@intel.com> *主题: *[edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses Introduce IsLinearAddressValid() function that will be used for validating memory addresses that would get dereferenced during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 382 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 16 + 2 files changed, 398 insertions(+) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index 867c5c01d6..52b3eb1463 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -14,6 +14,9 @@ #include "CpuExceptionCommon.h" +#include +#include + // // Error code flag indicating whether or not an error code will be // pushed on the stack if an exception occurs. @@ -194,3 +197,382 @@ GetPdbFileName ( } } } + +/** + Check if a linear address is valid by walking the page tables in 4-level + paging mode. + + @param[in] Cr3 CR3 control register. + @param[in] MaxPhyAddrBits MAXPHYADDRBITS bits. + @param[in] LinearAddress Linear address to be checked. +**/ +STATIC +BOOLEAN +Do4LevelPagingModeCheck ( + IN UINTN Cr3, + IN UINT8 MaxPhyAddrBits, + IN UINTN LinearAddress + ) +{ + UINT64 PhysicalAddress; + UINT64 *Pml4TableEntry; + UINT64 *PageDirPtrTableEntry; + UINT64 *PageDirEntry; + UINT64 *PageTableEntry; + + // + // In 4-level paging mode, linear addresses are 48 bits wide + // + if ((UINT64)LinearAddress > (1ULL << 48) - 1) { + return FALSE; + } + + // + // Calculate physical address of PML4E + // + PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); + + Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check if a PDPTE is present + // + if ((*Pml4TableEntry & BIT0) == 0) { + return FALSE; + } + + // + // Calculate physical address of PDPTE + // + PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 30) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*PageDirPtrTableEntry) - 1)) == 0); + + PageDirPtrTableEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check whether a PDPTE or 1GiB page entry is present + // + if ((*PageDirPtrTableEntry & BIT0) == 0) { + return FALSE; + } + + // + // Check if PDPTE maps an 1GiB page + // + if ((*PageDirPtrTableEntry & BIT7) != 0) { + return TRUE; + } + + // + // Calculate physical address of PDE + // + PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) - 1) << + 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 21) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*PageDirEntry) - 1)) == 0); + + PageDirEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check whether a PDE or a 2MiB page entry is present + // + if ((*PageDirEntry & BIT0) == 0) { + return FALSE; + } + + // + // Check if PDE maps a 2MiB page + // + if ((*PageDirEntry & BIT7) != 0) { + return TRUE; + } + + // + // Calculate physical address of PTE + // + PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress
[edk2] [RFC v4 2/6] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName()
This function will be used by both IA32 and X64 exception handling in order to print out image module names during stack unwinding. Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 60 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 14 + UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 59 --- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index dbfaae1d30..f62ab8c48c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -54,6 +54,11 @@ CONST CHAR8 *mExceptionNameStr[] = { #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *)) +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Get ASCII format string exception name by exception type. @@ -177,4 +182,57 @@ ReadAndVerifyVectorInfo ( VectorInfo ++; } return EFI_SUCCESS; -} \ No newline at end of file +} + +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index e10d9379d5..64c7094513 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -327,5 +327,19 @@ AsmGetTssTemplateMap ( OUT EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap ); +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ); + #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 19bfaa329a..d3a3878b3d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,11 +14,6 @@ #include "CpuExceptionCommon.h" -// -// Unknown PDB file name -// -GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; - /** Return address map of exception handler template so that C code can generate exception tables. @@ -403,60 +398,6 @@ DumpCpuContext ( ); } -/** - Get absolute path and file name of PDB file in PE/COFF image. - - @param[in] ImageBaseBase address of PE/COFF image. - @param[out] PdbAbsoluteFilePath Absolute path of PDB file. - @param[out] PdbFileName File name of PDB file. -**/ -STATIC -VOID -GetPdbFileName ( - IN UINTNImageBase, - OUT CHAR8**PdbAbsoluteFilePath, - OUT CHAR8**PdbFileName - ) -{ - VOID *PdbPointer; - CHAR8 *Str; - - // - // Get PDB file name from PE/COFF image - // - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); - if (PdbPointer == NULL) { -// -// No PDB file name found. Set it to an unknown file name. -// -*PdbFileName = (C
[edk2] [RFC v4 4/6] UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses
Introduce IsLinearAddressValid() function that will be used for validating memory addresses that would get dereferenced during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 382 UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 16 + 2 files changed, 398 insertions(+) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index 867c5c01d6..52b3eb1463 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -14,6 +14,9 @@ #include "CpuExceptionCommon.h" +#include +#include + // // Error code flag indicating whether or not an error code will be // pushed on the stack if an exception occurs. @@ -194,3 +197,382 @@ GetPdbFileName ( } } } + +/** + Check if a linear address is valid by walking the page tables in 4-level + paging mode. + + @param[in] Cr3 CR3 control register. + @param[in] MaxPhyAddrBits MAXPHYADDRBITS bits. + @param[in] LinearAddress Linear address to be checked. +**/ +STATIC +BOOLEAN +Do4LevelPagingModeCheck ( + IN UINTNCr3, + IN UINT8MaxPhyAddrBits, + IN UINTNLinearAddress + ) +{ + UINT64 PhysicalAddress; + UINT64 *Pml4TableEntry; + UINT64 *PageDirPtrTableEntry; + UINT64 *PageDirEntry; + UINT64 *PageTableEntry; + + // + // In 4-level paging mode, linear addresses are 48 bits wide + // + if ((UINT64)LinearAddress > (1ULL << 48) - 1) { +return FALSE; + } + + // + // Calculate physical address of PML4E + // + PhysicalAddress = (UINT64)Cr3 & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 39) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*Pml4TableEntry) - 1)) == 0); + + Pml4TableEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check if a PDPTE is present + // + if ((*Pml4TableEntry & BIT0) == 0) { +return FALSE; + } + + // + // Calculate physical address of PDPTE + // + PhysicalAddress = *Pml4TableEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 30) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*PageDirPtrTableEntry) - 1)) == 0); + + PageDirPtrTableEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check whether a PDPTE or 1GiB page entry is present + // + if ((*PageDirPtrTableEntry & BIT0) == 0) { +return FALSE; + } + + // + // Check if PDPTE maps an 1GiB page + // + if ((*PageDirPtrTableEntry & BIT7) != 0) { +return TRUE; + } + + // + // Calculate physical address of PDE + // + PhysicalAddress = *PageDirPtrTableEntry & (((1ULL << MaxPhyAddrBits) - 1) << + 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 21) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*PageDirEntry) - 1)) == 0); + + PageDirEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check whether a PDE or a 2MiB page entry is present + // + if ((*PageDirEntry & BIT0) == 0) { +return FALSE; + } + + // + // Check if PDE maps a 2MiB page + // + if ((*PageDirEntry & BIT7) != 0) { +return TRUE; + } + + // + // Calculate physical address of PTE + // + PhysicalAddress = *PageDirEntry & (((1ULL << MaxPhyAddrBits) - 1) << 12); + PhysicalAddress |= (((UINT64)LinearAddress >> 12) & 0x1FF) << 3; + + ASSERT ((PhysicalAddress & (sizeof (*PageTableEntry) - 1)) == 0); + + PageTableEntry = (UINT64 *)(UINTN)PhysicalAddress; + + // + // Check if PTE maps a 4KiB page + // + if ((*PageTableEntry & BIT0) == 0) { +return FALSE; + } + + return TRUE; +} + +/** + Check if a linear address is valid by walking the page tables in 32-bit paging + mode. + + @param[in] Cr3 CR3 control register. + @param[in] Cr4 CR4 control register. + @param[in] LinearAddress Linear address to be checked. +**/ +STATIC +BOOLEAN +Do32BitPagingModeCheck ( + IN UINTNCr3, + IN UINTNCr4, + IN UINTNLinearAddress + ) +{ + UINT64 PhysicalAddress; + UINT32 *PageDirEntry; + UINT32 *PageTableEntry; + + if (LinearAddress > MAX_UINT32) { +return FALSE; + } + + // + // Calculate physical address of PDE + // + PhysicalAddress = (UINT32)Cr3 & (((1ULL << 20) - 1) << 12); + PhysicalAdd
[edk2] [RFC v4 5/6] UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers
Validate all possible memory dereferences during stack traces in IA32 and X64 CPU exceptions. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Brian Johnson <brian.john...@hpe.com> Requested-by: Jiewen Yao <jiewen@intel.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 143 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 75 +- 2 files changed, 210 insertions(+), 8 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 25e02fbbc1..9b52d4f6d2 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -398,6 +398,96 @@ DumpCpuContext ( ); } +/** + Check if a logical address is valid. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[in] SegmentSelectorSegment selector. + @param[in] Offset Offset or logical address. +**/ +STATIC +BOOLEAN +IsLogicalAddressValid ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT16 SegmentSelector, + IN UINTNOffset + ) +{ + IA32_SEGMENT_DESCRIPTOR *SegmentDescriptor; + UINT32 SegDescBase; + UINT32 SegDescLimit; + UINTNSegDescLimitInBytes; + + // + // Check for valid input parameters + // + if (SegmentSelector == 0 || Offset == 0) { +return FALSE; + } + + // + // Check whether to look for a segment descriptor in GDT or LDT table + // + if ((SegmentSelector & BIT2) == 0) { +// +// Get segment descriptor from GDT table +// +SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( +(UINTN)SystemContext.SystemContextIa32->Gdtr[0] + +((SegmentSelector >> 3) * 8) +); + } else { +// +// Get segment descriptor from LDT table +// +SegmentDescriptor = + (IA32_SEGMENT_DESCRIPTOR *)( +(UINTN)SystemContext.SystemContextIa32->Ldtr + +((SegmentSelector >> 3) * 8) +); + } + + // + // Get segment descriptor's base address + // + SegDescBase = SegmentDescriptor->Bits.BaseLow | +(SegmentDescriptor->Bits.BaseMid << 16) | +(SegmentDescriptor->Bits.BaseHigh << 24); + + // + // Get segment descriptor's limit + // + SegDescLimit = SegmentDescriptor->Bits.LimitLow | +(SegmentDescriptor->Bits.LimitHigh << 16); + + // + // Calculate segment descriptor's limit in bytes + // + if (SegmentDescriptor->Bits.G == 1) { +SegDescLimitInBytes = (UINTN)SegDescLimit * SIZE_4KB; + } else { +SegDescLimitInBytes = SegDescLimit; + } + + // + // Make sure to not access beyond a segment limit boundary + // + if (Offset + SegDescBase > SegDescLimitInBytes) { +return FALSE; + } + + // + // Check if the translated logical address (or linear address) is valid + // + return IsLinearAddressValid ( +SystemContext.SystemContextIa32->Cr0, +SystemContext.SystemContextIa32->Cr3, +SystemContext.SystemContextIa32->Cr4, +Offset + SegDescBase +); +} + /** Dump stack trace. @@ -459,6 +549,20 @@ DumpStackTrace ( InternalPrintMessage ("\nCall trace:\n"); for (;;) { +// +// Check for valid frame pointer +// +if (!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp + 4) || +!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp)) { + InternalPrintMessage ("%a: attempted to dereference an invalid frame " +"pointer at 0x%08x\n", __FUNCTION__, Ebp); + break; +} + // // Print stack frame in the following format: // @@ -588,6 +692,16 @@ DumpImageModuleNames ( // Walk through call stack and find next module names // for (;;) { +if (!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp) || +!IsLogicalAddressValid (SystemContext, +SystemContext.SystemContextIa32->Ss, +(UINTN)Ebp + 4)) { + InternalPrintMessage ("%a: attempted to dereference an invalid frame " +"pointer at 0x%08x\n", __FUNCTION__, Ebp); +} + // // Set EIP with return address from current stack frame // @@ -651,16 +765,23 @@
[edk2] [RFC v4 6/6] UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses
Remove the supurious '- 1' when calculating the IP addresses during the stack traces. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Requested-by: Jeff Fan <vanjeff_...@hotmail.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 2 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 9b52d4f6d2..e2a3341286 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -573,7 +573,7 @@ DumpStackTrace ( *UnwoundStacksCount - 1, Eip, ImageBase, - Eip - ImageBase - 1, + Eip - ImageBase, Ebp, PdbFileName ); diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 8067c34122..5ae3aa4e73 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -717,7 +717,7 @@ DumpStackTrace ( *UnwoundStacksCount - 1, Rip, ImageBase, - Rip - ImageBase - 1, + Rip - ImageBase, Rbp, PdbFileName ); -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v4 1/6] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 376 +++- 1 file changed, 374 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 1dcf4277de..19bfaa329a 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -398,6 +403,357 @@ DumpCpuContext ( ); } +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned stack pointer. \n"); +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + +// +// Point to next stack +// +CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID*EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP address + // + Rip = SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp = SystemContext.SystemContextX64->Rbp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase = PeCoffSearchImageBase (Rip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find image module names. "); +return; + } + + // + // Set last PE/COFF image base address + // + LastImageBase = ImageBase; + + // + // Get initial PE/COFF image's entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, ); + if (EFI_ERROR (Status)) { +EntryPoint = NULL; + } + + // + // Get file name and absolute path of initial PDB file + // + GetPdbFileName (ImageBase, , ); + + // + // Print out initial image module name (if any) + //
[edk2] [RFC v4 3/6] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support
This patch adds stack trace support during a IA32 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 42 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 11 - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 310 +++- 3 files changed, 308 insertions(+), 55 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index f62ab8c48c..867c5c01d6 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -109,48 +109,6 @@ InternalPrintMessage ( SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); } -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ) -{ - EFI_STATUS Status; - UINTNPe32Data; - VOID *PdbPointer; - VOID *EntryPoint; - - Pe32Data = PeCoffSearchImageBase (CurrentEip); - if (Pe32Data == 0) { -InternalPrintMessage (" Can't find image information. \n"); - } else { -// -// Find Image Base entry point -// -Status = PeCoffLoaderGetEntryPoint ((VOID *) Pe32Data, ); -if (EFI_ERROR (Status)) { - EntryPoint = NULL; -} -InternalPrintMessage (" Find image "); -PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); -if (PdbPointer != NULL) { - InternalPrintMessage ("%a", PdbPointer); -} else { - InternalPrintMessage ("(No PDB) " ); -} -InternalPrintMessage ( - " (ImageBase=%016lp, EntryPoint=%016p) \n", - (VOID *) Pe32Data, - EntryPoint - ); - } -} - /** Read and save reserved vector information diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 64c7094513..ec46c2d9d3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -130,17 +130,6 @@ InternalPrintMessage ( ... ); -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ); - /** Display CPU information. diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index 6ac8549839..25e02fbbc1 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -398,6 +398,296 @@ DumpCpuContext ( ); } +/** + Dump stack trace. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackTrace ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + Eip = SystemContext.SystemContextIa32->Eip; + + // + // Set current frame pointer address + // + Ebp = SystemContext.SystemContextIa32->Ebp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Ebp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase = PeCoffSearchImageBase (Eip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find backtrace information. "); +return; + } + + // + // Get PDB file name from initial PE/COFF image + // + GetPdbFileName (ImageBase, NULL, ); + + // + // Initialize count of unwound stacks + // + *UnwoundStacksCount = 1; + + // + // Print out back trace + // + InternalPrintMessage ("\nCall trace:\n"); + + for (;;) { +// +// Print stack frame in the following format: +// +// # @ + (EBP) in [ | ] +// +InternalPrintMessage ( + "%d 0x%08x @ 0x%08x+0x%x (0x%08x) in %a\n", + *UnwoundStacksCount - 1, +
[edk2] [RFC v4 0/6] Stack trace support in X64 exception handling
Hi, This series adds stack trace support during IA32 and X64 CPU exceptions. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. The current limitation is that it relies on available frame pointers (GCC only) in order to successfully unwind the stack. (Sorry for the very long delay - I was very busy working on something else and then went to vacations) Jiewen, I have tested it with VS2015x86 and the stack trace just hanged when printing out the first EIP (that is, no frame pointer at all). Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v4 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Brian Johnson <brian.john...@hpe.com> Cc: Jeff Fan <vanjeff_...@hotmail.com> Cc: Jiewen Yao <jiewen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@paulo.ac> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. v2 -> v3: * Fixed wrong assumption about "RIP < ImageBase" to start searching for another PE/COFF image. That is, RIP may point to lower and higher addresses for any other PE/COFF images. Both IA32 & X64. (Thanks Andrew & Jiewen) * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) v3 -> v4: * Validate all frame/stack pointer addresses before dereferencing them as requested by Brian & Jiewen. * Correctly print out IP addresses during the stack traces (by Jeff) Paulo Alcantara (6): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Add helper to valid memory addresses UefiCpuPkg/CpuExceptionHandlerLib: Ensure valid frame/stack pointers UefiCpuPkg/CpuExceptionHandlerLib: Correctly print IP addresses UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 484 ++-- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 41 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 445 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 384 +++- 4 files changed, 1296 insertions(+), 58 deletions(-) -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] 答复: [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Hi Jeff, (sorry for the late response) On 11/17/2017 5:24 AM, Fan Jeff wrote: Paulo, I don't understand why you - 1 when calculating EIP offset in image, it confused me. That's an offset relative to the PE/COFF image base: 0 - (ImageBase + ImageBaseSize - 1) Doesn't that look right to you? Thanks Paulo + for (;;) { + // + // Print stack frame in the following format: + // + // # @ + (RBP) in [ | ] + // + InternalPrintMessage ( + "%d 0x%016lx @ 0x%016lx+0x%x (0x%016lx) in %a\n", + *UnwoundStacksCount - 1, + Rip, + ImageBase, + Rip - ImageBase - 1, // + Rbp, + PdbFileName + ); + Jeff *发件人:* edk2-devel <edk2-devel-boun...@lists.01.org> 代表 Paulo Alcantara <pca...@zytor.com> *发送时间:* 2017年11月17日 5:56 *收件人:* edk2-devel@lists.01.org *抄送:* Laszlo Ersek; Eric Dong *主题:* [edk2] [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 376 +++- 1 file changed, 374 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 65f0cff680..fe776ccc2d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -242,6 +247,357 @@ DumpCpuContext ( ); } +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBase Base address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTN ImageBase, + OUT CHAR8 **PdbAbsoluteFilePath, + OUT CHAR8 **PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { + // + // No PDB file name found. Set it to an unknown file name. + // + *PdbFileName = (CHAR8 *)mUnknownPdbFileName; + if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; + } + } else { + // + // Get file name portion out of PDB file in PE/COFF image + // + Str = (CHAR8 *)((UINTN)PdbPointer + + AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); + for (; *Str != '/' && *Str != '\\'; Str--) { + ; + } + + // + // Set PDB file name (also skip trailing path separator: '/' or '\\') + // + *PdbFileName = Str + 1; + + if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; + } + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTN UnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { + InternalPrintMessage (" Unaligned stack pointer. \n"); + return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { + InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + + // + // Point to next stack + // + CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID *EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP ad
Re: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Hi Jiewen, (sorry for the late response) On 11/17/2017 1:43 AM, Yao, Jiewen wrote: Thanks for your reply. Comments below: -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Friday, November 17, 2017 6:13 AM To: Yao, Jiewen <jiewen@intel.com> Cc: Paulo Alcantara <pca...@zytor.com>; edk2-devel@lists.01.org; Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> Subject: RE: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support Hi Jiewen, On Wed, November 15, 2017 11:57 pm, Yao, Jiewen wrote: Hi Paulo Thanks to bring this cool feature. I have same feeling as Jeff Fan. It is great! I have some questions, hope you can clarify. 1) Would you please let us know which tool change is validated? Such as MSVC, or GCC? GCC only. This should not work on MSVC because it relies on frame pointers. [Jiewen] Not work is OK. But my question is more about: Have you tested? Or have you tried? Do you see basic exception information can be dumped without any problem for MSVC? Or do you see system crash immediately for MSVC? No, I haven't tried it. I built it with VS2015 and just run 'objdump -x -D' in an arbitrary .efi to check whether RBP was being used in function's prologues. They weren't and then I didn't even give it try. I'll test it though and then let you know its behavior. 2) Would you please let us know which phase is validated? Such as PEI PreMemory, PEI PostMemory, DXE, SMM? DXE. I'm currently testing it by placing a random "CpuBreakpoint ()" in PartitionDxe driver. [Jiewen] Ummm. Based upon the fact that the code you update may be used in all those phases. I recommend to validate them in the final patch. Sure. 3) Would you please let us know if there is any special condition validated? Such as code is in an interrupt handler, SMM initialization code, thunk code during mode switch, etc. I ask this because I have seen lots of discussion on sanity check, to avoid double exception. At the moment I'm only ensuring proper aligned RSP and ESP values. But we still need to validate the RIP values, etc. as Andrew and Brian suggested. [Jiewen] OK. I look forward to seeing your patch to validate more. Same as #2. I suggest you validate all those corner cases in the final patch. I will for sure. 4) We supported some security feature to create a hole in normal memory map, such as PageGuard, StackGuard, SMM communication protection, etc. Accessing those memory directly will cause #PF immediately. Would you please let us know how we detect that case, to avoid RIP or RSP fail to the non-present page? Sorry. I have no idea :-( I'd hope to get some help from you guys. [Jiewen] One possible solution is to scan page table, before access this address, to make sure you are accessing present page. You can also filer invalid address directly by checking CPUID physical address bit before that. The invalid address will cause #GP instead of #PF. Oh, looks like a great solution. I'll try them out and let you know if it worked. Thank you!! All I all, I would like to clarify the goal for exception lib: whatever exception condition the BIOS meets, the exception handler can always dump the *basic* exception information and halt. The missing of advanced symbol info is acceptable. But system crash, when we want to dump the advanced info, is not the best choice. You're right. I'll make sure to validate it as much as possible and avoid such issues. Please, give me some more time because currently I've got pretty busy with something else. I really appreciate your help. Thanks! Paulo 5) May I know why we check RIP < ImageBase? Is that legal or illegal if RIP > ImageBase+ImageSize, but RIP in another PE/COFF image? That check was a wrong assumption that I had in the beginning. RIP may point to either lower or higher addresses where the other PE/COFF images are located. Fixed it in v3. [Jiewen] Great. Thanks. Sorry for the delay in the response. I'm only able to work on this in my free time. Thanks! Paulo +// +// Check if RIP is within another PE/COFF image base address +// +if (Rip < ImageBase) { + // + // Search for the respective PE/COFF image based on RIP + // Thank you Yao Jiewen -Original Message- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Paulo Alcantara Sent: Thursday, November 16, 2017 9:18 AM To: edk2-devel@lists.01.org Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> Subject: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo
Re: [edk2] [PATCH v2 1/2] MdeModulePkg/PartitionDxe: Merge the discovery of ElTorito into UDF
On Thu, November 16, 2017 5:47 am, Hao Wu wrote: > In order to create all of the children (El Torito standard and UDF) for > a CD/DVD media in an entry of the PartitionDriverBindingStart(), this > commit merges the discovery of the El Torito feature > (PartitionInstallElToritoChildHandles) into function > PartitionInstallUdfChildHandles. > > Cc: Paulo Alcantara <pca...@zytor.com> > Cc: Ruiyu Ni <ruiyu...@intel.com> > Cc: Star Zeng <star.z...@intel.com> > Cc: Eric Dong <eric.d...@intel.com> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Hao Wu <hao.a...@intel.com> > --- > MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c | 7 +++-- > MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 27 > ++++++-- > 2 files changed, 28 insertions(+), 6 deletions(-) Reviewed-by: Paulo Alcantara <pca...@zytor.com> Thanks! Paulo > > diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c > b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c > index f6030e0897..603abfe55a 100644 > --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c > +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c > @@ -43,7 +43,6 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = { > // > PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = { >PartitionInstallGptChildHandles, > - PartitionInstallElToritoChildHandles, >PartitionInstallMbrChildHandles, >PartitionInstallUdfChildHandles, >NULL > @@ -306,9 +305,9 @@ PartitionDriverBindingStart ( >if (BlockIo->Media->MediaPresent || >(BlockIo->Media->RemovableMedia && > !BlockIo->Media->LogicalPartition)) { > // > -// Try for GPT, then El Torito, then UDF, and then legacy MBR > partition > -// types. If the media supports a given partition type install child > handles > -// to represent the partitions described by the media. > +// Try for GPT, then legacy MBR partition types, and then UDF and El > Torito. > +// If the media supports a given partition type install child handles > to > +// represent the partitions described by the media. > // > Routine = [0]; > while (*Routine != NULL) { > diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c > b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c > index 7eee748958..5aac5640f6 100644 > --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c > +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c > @@ -688,8 +688,10 @@ PartitionInstallUdfChildHandles ( >EFI_PARTITION_INFO_PROTOCOL PartitionInfo; >EFI_LBA StartingLBA; >EFI_LBA EndingLBA; > + BOOLEAN ChildCreated; > >Media = BlockIo->Media; > + ChildCreated = FALSE; > >// >// Check if UDF logical block size is multiple of underlying device > block size > @@ -704,11 +706,29 @@ PartitionInstallUdfChildHandles ( >} > >// > + // Detect El Torito feature first. > + // And always continue to search for UDF. > + // > + Status = PartitionInstallElToritoChildHandles ( > + This, > + Handle, > + DiskIo, > + DiskIo2, > + BlockIo, > + BlockIo2, > + DevicePath > + ); > + if (!EFI_ERROR (Status)) { > +DEBUG ((DEBUG_INFO, "PartitionDxe: El Torito standard found on handle > 0x%p.\n", Handle)); > +ChildCreated = TRUE; > + } > + > + // >// Search for an UDF file system on block device >// >Status = FindUdfFileSystem (BlockIo, DiskIo, , ); >if (EFI_ERROR (Status)) { > -return EFI_NOT_FOUND; > +return (ChildCreated ? EFI_SUCCESS : EFI_NOT_FOUND); >} > >// > @@ -735,6 +755,9 @@ PartitionInstallUdfChildHandles ( > EndingLBA, > Media->BlockSize > ); > + if (EFI_ERROR (Status)) { > +return (ChildCreated ? EFI_SUCCESS : Status); > + } > > - return Status; > + return EFI_SUCCESS; > } > -- > 2.12.0.windows.1 > > -- Paulo Alcantara, HP Inc. Speaking for myself only. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
tack frames. >> +**/ >> +STATIC >> +VOID >> +DumpStackTrace ( >> + IN EFI_SYSTEM_CONTEXT SystemContext, >> + OUT INTN *UnwondStacksCount >> + ) >> +{ >> + UINT64 Rip; >> + UINT64 Rbp; >> + UINTN ImageBase; >> + CHAR8 *PdbFileName; >> + >> + // >> + // Set current RIP address >> + // >> + Rip = SystemContext.SystemContextX64->Rip; >> + >> + // >> + // Set current frame pointer address >> + // >> + Rbp = SystemContext.SystemContextX64->Rbp; >> + >> + // >> + // Get initial PE/COFF image base address from current RIP >> + // >> + ImageBase = PeCoffSearchImageBase (Rip); >> + if (ImageBase == 0) { >> +InternalPrintMessage (" Could not find backtrace information. >> "); >> +return; >> + } >> + >> + // >> + // Get PDB file name from initial PE/COFF image >> + // >> + GetPdbFileName (ImageBase, NULL, ); >> + >> + // >> + // Initialize count of unwond stacks >> + // >> + *UnwondStacksCount = 1; >> + >> + // >> + // Print out back trace >> + // >> + InternalPrintMessage ("\nCall trace:\n"); >> + >> + for (;;) { >> +// >> +// Print stack frame in the following format: >> +// >> +// # @ + (RBP) in [ | ] >> +// >> +InternalPrintMessage ( >> + "%d 0x%016lx @ 0x%016lx+0x%x (0x%016lx) in %a\n", >> + *UnwondStacksCount - 1, >> + Rip, >> + ImageBase, >> + Rip - ImageBase - 1, >> + Rbp, >> + PdbFileName >> + ); >> + >> +// >> +// Set RIP with return address from current stack frame >> +// >> +Rip = *(UINT64 *)((UINTN)Rbp + 8); >> + >> +// >> +// If RIP is zero, then stop unwinding the stack >> +// >> +if (Rip == 0) { >> + break; >> +} >> + >> +// >> +// Check if RIP is within another PE/COFF image base address >> +// >> +if (Rip < ImageBase) { >> + // >> + // Search for the respective PE/COFF image based on RIP >> + // >> + ImageBase = PeCoffSearchImageBase (Rip); >> + if (ImageBase == 0) { >> +// >> +// Stop stack trace >> +// >> +break; >> + } >> + >> + // >> + // Get PDB file name >> + // >> + GetPdbFileName (ImageBase, NULL, ); >> +} >> + >> +// >> +// Unwind the stack >> +// >> +Rbp = *(UINT64 *)(UINTN)Rbp; >> + >> +// >> +// Increment count of unwond stacks >> +// >> +(*UnwondStacksCount)++; >> + } >> +} >> + >> /** >> Display CPU information. >> >> @@ -254,9 +603,25 @@ DumpImageAndCpuContent ( >> IN EFI_SYSTEM_CONTEXT SystemContext >> ) >> { >> + INTN UnwondStacksCount; >> + >> + // >> + // Dump CPU context >> + // >> DumpCpuContext (ExceptionType, SystemContext); >> + >> + // >> + // Dump stack trace >> + // >> + DumpStackTrace (SystemContext, ); >> + >> + // >> + // Dump image module names >> + // >> + DumpImageModuleNames (SystemContext); >> + >> // >> - // Dump module image base and module entry point by RIP >> + // Dump stack contents >> // >> - DumpModuleImageInfo (SystemContext.SystemContextX64->Rip); >> + DumpStackContents (SystemContext.SystemContextX64->Rsp, >> UnwondStacksCount); >> } >> > > > -- > Brian J. Johnson > Enterprise X86 Lab > > Hewlett Packard Enterprise > > brian.john...@hpe.com > > ___ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel > -- Paulo Alcantara, HP Inc. Speaking for myself only. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Hi Jiewen, On Wed, November 15, 2017 11:57 pm, Yao, Jiewen wrote: > Hi Paulo > Thanks to bring this cool feature. > > I have same feeling as Jeff Fan. It is great! > > I have some questions, hope you can clarify. > 1) Would you please let us know which tool change is validated? Such as > MSVC, or GCC? GCC only. This should not work on MSVC because it relies on frame pointers. > 2) Would you please let us know which phase is validated? Such as PEI > PreMemory, PEI PostMemory, DXE, SMM? DXE. I'm currently testing it by placing a random "CpuBreakpoint ()" in PartitionDxe driver. > 3) Would you please let us know if there is any special condition > validated? Such as code is in an interrupt handler, SMM initialization > code, thunk code during mode switch, etc. > I ask this because I have seen lots of discussion on sanity check, to > avoid double exception. At the moment I'm only ensuring proper aligned RSP and ESP values. But we still need to validate the RIP values, etc. as Andrew and Brian suggested. > 4) We supported some security feature to create a hole in normal memory > map, such as PageGuard, StackGuard, SMM communication protection, etc. > Accessing those memory directly will cause #PF immediately. > Would you please let us know how we detect that case, to avoid RIP or RSP > fail to the non-present page? Sorry. I have no idea :-( I'd hope to get some help from you guys. > 5) May I know why we check RIP < ImageBase? Is that legal or illegal if > RIP > ImageBase+ImageSize, but RIP in another PE/COFF image? That check was a wrong assumption that I had in the beginning. RIP may point to either lower or higher addresses where the other PE/COFF images are located. Fixed it in v3. Sorry for the delay in the response. I'm only able to work on this in my free time. Thanks! Paulo >> +// >> +// Check if RIP is within another PE/COFF image base address >> +// >> +if (Rip < ImageBase) { >> + // >> + // Search for the respective PE/COFF image based on RIP >> + // > > Thank you > Yao Jiewen > > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of >> Paulo >> Alcantara >> Sent: Thursday, November 16, 2017 9:18 AM >> To: edk2-devel@lists.01.org >> Cc: Laszlo Ersek <ler...@redhat.com>; Dong, Eric <eric.d...@intel.com> >> Subject: [edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add >> stack >> trace support >> >> This patch adds stack trace support during a X64 CPU exception. >> >> It will dump out back trace, stack contents as well as image module >> names that were part of the call stack. >> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >> --- >> UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | >> 369 >> +++- >> 1 file changed, 367 insertions(+), 2 deletions(-) >> >> diff --git >> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c >> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c >> index 65f0cff680..11cd7c9e1c 100644 >> --- >> a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c >> +++ >> b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c >> @@ -14,6 +14,11 @@ >> >> #include "CpuExceptionCommon.h" >> >> +// >> +// Unknown PDB file name >> +// >> +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 >> *mUnknownPdbFileName = ""; >> + >> /** >>Return address map of exception handler template so that C code can >> generate >>exception tables. >> @@ -242,6 +247,350 @@ DumpCpuContext ( >> ); >> } >> >> +/** >> + Get absolute path and file name of PDB file in PE/COFF image. >> + >> + @param[in] ImageBaseBase address of PE/COFF image. >> + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. >> + @param[out] PdbFileName File name of PDB file. >> +**/ >> +STATIC >> +VOID >> +GetPdbFileName ( >> + IN UINTNImageBase, >> + OUT CHAR8**PdbAbsoluteFilePath, >> + OUT CHAR8**PdbFileName >> + ) >> +{ >> + VOID *PdbPointer; >> + CHAR8 *Str; >> + >> + // >> + // Get PDB file name from PE/COFF image >> + // >> + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); >&
Re: [edk2] [RFC v2 0/3] Stack trace support in X64 exception handling
Hi Andrew, On Thu, November 16, 2017 3:01 am, Andrew Fish wrote: > Paulo, > > Those attached stack traces don't look right. What about the new ones? Thanks! Paulo > > Thanks, > > Andrew Fish > >> On Nov 15, 2017, at 5:46 PM, Paulo Alcantara <pca...@zytor.com> wrote: >> >> Hi, >> >> On 11/15/2017 11:18 PM, Paulo Alcantara wrote: >>> Hi, >>> This series adds stack trace support during a X64 CPU exception. >>> Informations like back trace, stack contents and image module names >>> (that were part of the call stack) will be dumped out. >>> We already have such support in ARM/AArch64 (IIRC) exception handling >>> (thanks to Ard), and then I thought we'd also deserve it in X64 and >>> IA-32 platforms. >>> What do you think guys? >>> BTW, I've tested this only with OVMF (X64 only), using: >>> - gcc-6.3.0, GCC5, NOOPT >>> Any other tests would be really appreciable. >>> Thanks! >>> Paulo >>> Repo: https://github.com/pcacjr/edk2.git >>> Branch: stacktrace_v2 >>> Cc: Rick Bramley <richard.bram...@hp.com> >>> Cc: Andrew Fish <af...@apple.com> >>> Cc: Eric Dong <eric.d...@intel.com> >>> Cc: Laszlo Ersek <ler...@redhat.com> >>> Cc: "Brian J. Johnson" <brian.john...@hpe.com> >>> Cc: Jeff Fan <jeff@intel.com> >>> Contributed-under: TianoCore Contribution Agreement 1.1 >>> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >>> --- >>> v1 -> v2: >>> * Add IA32 arch support (GCC toolchain only) >>> * Replace hard-coded stack alignment value (16) with >>> CPU_STACK_ALIGNMENT. >>> * Check for proper stack and frame pointer alignments. >>> * Fix initialization of UnwoundStacksCount to 1. >>> * Move GetPdbFileName() to common code since it will be used by both >>> IA32 and X64 implementations. >> >> Sorry for the delay in sending v2. It's holiday here :-) >> >> FWIW, I've attached two files which contain stack trace dumps of IA32 >> and X64 exceptions. >> >> The new IA32 arch support is still limited to GCC only (that is, relying >> on frame pointers), but I'll start investing in a new solution that >> would work on both MSVC and GCC toolchains -- probably this weekend. If >> I come up with something, I'll let you know. >> >> On IA32, I performed the same test as in X64 to trigger an NMI interrupt >> manually with: asm ("int $0x2") in PartitionDxe driver and watched out >> the call stack. The difference between the two dumps, regardless the CPU >> context, etc. is that we don't see the calls from PeiCore.dll. Then I >> figured out that the EIP gets a value of 0 before jumping to >> PartitionDxe's entry point. >> >> I guess that's related to the "push $0" that Andrew mentioned earlier so >> the debugger knows when to stop unwinding. Although I can't see a "push >> 0" equivalent neither in SwitchStack.nasm nor in SwitchStack.asm for X64 >> -- so we're able to see the calls within PeiCore.dll. >> >> Thanks! >> Paulo >> ___ >> edk2-devel mailing list >> edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> >> https://lists.01.org/mailman/listinfo/edk2-devel >> <https://lists.01.org/mailman/listinfo/edk2-devel> > -- Paulo Alcantara, HP Inc. Speaking for myself only. IA32 Exception Type - 03(#BP - Breakpoint) CPU Apic ID - EIP - 7DBCD580, CS - 0010, EFLAGS - 0206 EAX - , ECX - 7EEC8CFF, EDX - 7ED9C220, EBX - ESP - 7EEC8DDC, EBP - 7EEC8DDC, ESI - 0004, EDI - DS - 0008, ES - 0008, FS - 0008, GS - 0008, SS - 0008 CR0 - 0033, CR2 - , CR3 - , CR4 - 0640 DR0 - , DR1 - , DR2 - , DR3 - DR6 - 0FF0, DR7 - 0400 GDTR - 7EE97A90 0047, IDTR - 7E65B010 07FF LDTR - , TR - FXSAVE_STATE - 7EEC8B20 Call trace: 0 0x7DBCD580 @ 0x7DBCD000+0x57F (0x7EEC8DDC) in PartitionDxe.dll 1 0x7DBD41BE @ 0x7DBCD000+0x71BD (0x7EEC8DFC) in PartitionDxe.dll 2 0x7DBD456C @ 0x7DBCD000+0x756B (0x7EEC8E1C) in PartitionDxe.dll 3 0x7DBCF7F4 @ 0x7DBCD000+0x27F3 (0x7EEC8E4C) in PartitionDxe.dll 4 0x7EED9EA4 @ 0x7EEC9000+0x10EA3 (0x7EEC8E9C) in DxeCore.dll 5 0x7EEF1A8C @ 0x7EEC9000+0x28A8B (0x7EEC8EDC) in DxeCore.dll 6 0x7EEF3DD0 @ 0x7EEC9000+0x2ADCF (0x7EEC8FAC) in DxeCore.dll 7 0x7EEF44A5 @ 0x7EEC9000+0x2B4A4 (0x7EEC8FCC) in DxeCore.dll 8 0x7EECD272 @ 0x7EEC9000+0x4271 (0x7EEC8FEC) in DxeCore.dll Partitio
[edk2] [RFC v3 0/3] Stack trace support in X64 exception handling
Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v2 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: brian.john...@hpe.com Cc: jiewen@intel.com Cc: Jeff Fan <jeff@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. v2 -> v3: * Fixed wrong assumption about "RIP < ImageBase" to start searching for another PE/COFF image. That is, RIP may point to lower and higher addresses for any other PE/COFF images. Both IA32 & X64. (Thanks Andrew & Jiewen) * Fixed typo: unwond -> unwound. Both IA32 & X64. (Thanks Brian) Brian: I didn't have a chance to investigate on how to validate the RIP and RSP values yet as you've suggested, sorry. But I will any time soon. NOTE: This RFC for stack trace in IA32 & X64 supports *only* GCC at the moment. Paulo Alcantara (3): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 102 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 25 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 310 ++- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 317 +++- 4 files changed, 696 insertions(+), 58 deletions(-) -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v3 3/3] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support
This patch adds stack trace support during a IA32 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 42 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 11 - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 310 +++- 3 files changed, 308 insertions(+), 55 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index f62ab8c48c..867c5c01d6 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -109,48 +109,6 @@ InternalPrintMessage ( SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); } -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ) -{ - EFI_STATUS Status; - UINTNPe32Data; - VOID *PdbPointer; - VOID *EntryPoint; - - Pe32Data = PeCoffSearchImageBase (CurrentEip); - if (Pe32Data == 0) { -InternalPrintMessage (" Can't find image information. \n"); - } else { -// -// Find Image Base entry point -// -Status = PeCoffLoaderGetEntryPoint ((VOID *) Pe32Data, ); -if (EFI_ERROR (Status)) { - EntryPoint = NULL; -} -InternalPrintMessage (" Find image "); -PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); -if (PdbPointer != NULL) { - InternalPrintMessage ("%a", PdbPointer); -} else { - InternalPrintMessage ("(No PDB) " ); -} -InternalPrintMessage ( - " (ImageBase=%016lp, EntryPoint=%016p) \n", - (VOID *) Pe32Data, - EntryPoint - ); - } -} - /** Read and save reserved vector information diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 042207025e..478374d003 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -119,17 +119,6 @@ InternalPrintMessage ( ... ); -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ); - /** Display CPU information. diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index f2c39eb193..db8013a5af 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -210,6 +210,296 @@ DumpCpuContext ( ); } +/** + Dump stack trace. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackTrace ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwoundStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + Eip = SystemContext.SystemContextIa32->Eip; + + // + // Set current frame pointer address + // + Ebp = SystemContext.SystemContextIa32->Ebp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Ebp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase = PeCoffSearchImageBase (Eip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find backtrace information. "); +return; + } + + // + // Get PDB file name from initial PE/COFF image + // + GetPdbFileName (ImageBase, NULL, ); + + // + // Initialize count of unwound stacks + // + *UnwoundStacksCount = 1; + + // + // Print out back trace + // + InternalPrintMessage ("\nCall trace:\n"); + + for (;;) { +// +// Print stack frame in the following format: +// +// # @ + (EBP) in [ | ] +// +InternalPrintMessage ( + "%d 0x%08x @ 0x%08x+0x%x (0x%08x) in %a\n", + *UnwoundStacksCount - 1, +
[edk2] [RFC v3 2/3] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName()
This function will be used by both IA32 and X64 exception handling in order to print out image module names during stack unwinding. Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 60 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 14 + UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 59 --- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index dbfaae1d30..f62ab8c48c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -54,6 +54,11 @@ CONST CHAR8 *mExceptionNameStr[] = { #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *)) +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Get ASCII format string exception name by exception type. @@ -177,4 +182,57 @@ ReadAndVerifyVectorInfo ( VectorInfo ++; } return EFI_SUCCESS; -} \ No newline at end of file +} + +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 740a58828b..042207025e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -288,5 +288,19 @@ CommonExceptionHandlerWorker ( IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData ); +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ); + #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index fe776ccc2d..7f8ec65e1d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,11 +14,6 @@ #include "CpuExceptionCommon.h" -// -// Unknown PDB file name -// -GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; - /** Return address map of exception handler template so that C code can generate exception tables. @@ -247,60 +242,6 @@ DumpCpuContext ( ); } -/** - Get absolute path and file name of PDB file in PE/COFF image. - - @param[in] ImageBaseBase address of PE/COFF image. - @param[out] PdbAbsoluteFilePath Absolute path of PDB file. - @param[out] PdbFileName File name of PDB file. -**/ -STATIC -VOID -GetPdbFileName ( - IN UINTNImageBase, - OUT CHAR8**PdbAbsoluteFilePath, - OUT CHAR8**PdbFileName - ) -{ - VOID *PdbPointer; - CHAR8 *Str; - - // - // Get PDB file name from PE/COFF image - // - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); - if (PdbPointer == NULL) { -// -// No PDB file name found. Set it to an unknown file name.
[edk2] [RFC v3 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 376 +++- 1 file changed, 374 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 65f0cff680..fe776ccc2d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -242,6 +247,357 @@ DumpCpuContext ( ); } +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwoundStacksCount Count of unwound stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwoundStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned stack pointer. \n"); +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwoundStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + +// +// Point to next stack +// +CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID*EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + UINTN LastImageBase; + + // + // Set current RIP address + // + Rip = SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp = SystemContext.SystemContextX64->Rbp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase = PeCoffSearchImageBase (Rip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find image module names. "); +return; + } + + // + // Set last PE/COFF image base address + // + LastImageBase = ImageBase; + + // + // Get initial PE/COFF image's entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, ); + if (EFI_ERROR (Status)) { +EntryPoint = NULL; + } + + // + // Get file name and absolute path of initial PDB file + // + GetPdbFileName (ImageBase, , ); + + // + // Print out initial image module name (if any) +
Re: [edk2] [RFC v2 0/3] Stack trace support in X64 exception handling
Hi, On 11/15/2017 11:18 PM, Paulo Alcantara wrote: Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v2 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: "Brian J. Johnson" <brian.john...@hpe.com> Cc: Jeff Fan <jeff@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. Sorry for the delay in sending v2. It's holiday here :-) FWIW, I've attached two files which contain stack trace dumps of IA32 and X64 exceptions. The new IA32 arch support is still limited to GCC only (that is, relying on frame pointers), but I'll start investing in a new solution that would work on both MSVC and GCC toolchains -- probably this weekend. If I come up with something, I'll let you know. On IA32, I performed the same test as in X64 to trigger an NMI interrupt manually with: asm ("int $0x2") in PartitionDxe driver and watched out the call stack. The difference between the two dumps, regardless the CPU context, etc. is that we don't see the calls from PeiCore.dll. Then I figured out that the EIP gets a value of 0 before jumping to PartitionDxe's entry point. I guess that's related to the "push $0" that Andrew mentioned earlier so the debugger knows when to stop unwinding. Although I can't see a "push 0" equivalent neither in SwitchStack.nasm nor in SwitchStack.asm for X64 -- so we're able to see the calls within PeiCore.dll. Thanks! Paulo X64 Exception Type - 02(NMI Interrupt) CPU Apic ID - RIP - 7EC30266, CS - 0038, RFLAGS - 0202 RAX - 7FE71018, RCX - 7F34F498, RDX - 7FE71018 RBX - 00810248, RSP - 7FEE4C70, RBP - 7FEE4CB0 RSI - 0007, RDI - 7F34E018 R8 - 7EC32DC8, R9 - 7F34E298, R10 - 0036 R11 - 00D7, R12 - , R13 - R14 - , R15 - DS - 0030, ES - 0030, FS - 0030 GS - 0030, SS - 0030 CR0 - 80010033, CR2 - , CR3 - 7FE83000 CR4 - 0668, CR8 - DR0 - , DR1 - , DR2 - DR3 - , DR6 - 0FF0, DR7 - 0400 GDTR - 7FE71A98 0047, LDTR - IDTR - 7F7AB018 0FFF, TR - FXSAVE_STATE - 7FEE48D0 Call trace: 0 0x7EC30266 @ 0x7EC28000+0x8265 (0x7FEE4CB0) in PartitionDxe.dll 1 0x7EC3063D @ 0x7EC28000+0x863C (0x7FEE4CE0) in PartitionDxe.dll 2 0x7EC2B116 @ 0x7EC28000+0x3115 (0x7FEE4D20) in PartitionDxe.dll 3 0x7FEF8A15 @ 0x7EC28000+0x12D0A14 (0x7FEE4DB0) in PartitionDxe.dll 4 0x7FF10F0A @ 0x7EC28000+0x12E8F09 (0x7FEE4E30) in PartitionDxe.dll 5 0x7FF13445 @ 0x7EC28000+0x12EB444 (0x7FEE4F60) in PartitionDxe.dll 6 0x7FF13BC9 @ 0x7EC28000+0x12EBBC8 (0x7FEE4F90) in PartitionDxe.dll 7 0x7FEE9DDE @ 0x7EC28000+0x12C1DDD (0x7FEE4FC0) in PartitionDxe.dll 8 0x7FF5B75F @ 0x7EC28000+0x133375E (0x7BFDC840) in PartitionDxe.dll 9 0x7FF61551 @ 0x7EC28000+0x1339550 (0x7BFDC8C0) in PartitionDxe.dll 10 0x7FF6031D @ 0x7EC28000+0x133831C (0x7BFDCA30) in PartitionDxe.dll 11 0x7FF6CDCB @ 0x7EC28000+0x1344DCA (0x7BFDCF80) in PartitionDxe.dll 12 0x008286F4 @ 0x00820140+0x85B3 (0x7BFDD4D0) in PeiCore.dll 13 0x00830940 @ 0x00820140+0x107FF (0x00817600) in PeiCore.dll 14 0x00831585 @ 0x00820140+0x11444 (0x008176D0) in PeiCore.dll 15 0
[edk2] [RFC v2 0/3] Stack trace support in X64 exception handling
Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_v2 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: "Brian J. Johnson" <brian.john...@hpe.com> Cc: Jeff Fan <jeff@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- v1 -> v2: * Add IA32 arch support (GCC toolchain only) * Replace hard-coded stack alignment value (16) with CPU_STACK_ALIGNMENT. * Check for proper stack and frame pointer alignments. * Fix initialization of UnwoundStacksCount to 1. * Move GetPdbFileName() to common code since it will be used by both IA32 and X64 implementations. Paulo Alcantara (3): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName() UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 102 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 25 +- UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 303 ++- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 310 +++- 4 files changed, 682 insertions(+), 58 deletions(-) -- 2.14.3 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC v2 3/3] UefiCpuPkg/CpuExceptionHandlerLib/Ia32: Add stack trace support
This patch adds stack trace support during a IA32 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c| 42 --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h| 11 - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 303 +++- 3 files changed, 301 insertions(+), 55 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index f62ab8c48c..867c5c01d6 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -109,48 +109,6 @@ InternalPrintMessage ( SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); } -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ) -{ - EFI_STATUS Status; - UINTNPe32Data; - VOID *PdbPointer; - VOID *EntryPoint; - - Pe32Data = PeCoffSearchImageBase (CurrentEip); - if (Pe32Data == 0) { -InternalPrintMessage (" Can't find image information. \n"); - } else { -// -// Find Image Base entry point -// -Status = PeCoffLoaderGetEntryPoint ((VOID *) Pe32Data, ); -if (EFI_ERROR (Status)) { - EntryPoint = NULL; -} -InternalPrintMessage (" Find image "); -PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *) Pe32Data); -if (PdbPointer != NULL) { - InternalPrintMessage ("%a", PdbPointer); -} else { - InternalPrintMessage ("(No PDB) " ); -} -InternalPrintMessage ( - " (ImageBase=%016lp, EntryPoint=%016p) \n", - (VOID *) Pe32Data, - EntryPoint - ); - } -} - /** Read and save reserved vector information diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 042207025e..478374d003 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -119,17 +119,6 @@ InternalPrintMessage ( ... ); -/** - Find and display image base address and return image base and its entry point. - - @param CurrentEip Current instruction pointer. - -**/ -VOID -DumpModuleImageInfo ( - IN UINTN CurrentEip - ); - /** Display CPU information. diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c index f2c39eb193..169a0b660e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c @@ -210,6 +210,289 @@ DumpCpuContext ( ); } +/** + Dump stack trace. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. + @param[out] UnwondStacksCount Count of unwond stack frames. +**/ +STATIC +VOID +DumpStackTrace ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT INTN *UnwondStacksCount + ) +{ + UINT32 Eip; + UINT32 Ebp; + UINTN ImageBase; + CHAR8 *PdbFileName; + + // + // Set current EIP address + // + Eip = SystemContext.SystemContextIa32->Eip; + + // + // Set current frame pointer address + // + Ebp = SystemContext.SystemContextIa32->Ebp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Ebp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current EIP + // + ImageBase = PeCoffSearchImageBase (Eip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find backtrace information. "); +return; + } + + // + // Get PDB file name from initial PE/COFF image + // + GetPdbFileName (ImageBase, NULL, ); + + // + // Initialize count of unwond stacks + // + *UnwondStacksCount = 1; + + // + // Print out back trace + // + InternalPrintMessage ("\nCall trace:\n"); + + for (;;) { +// +// Print stack frame in the following format: +// +// # @ + (EBP) in [ | ] +// +InternalPrintMessage ( + "%d 0x%08x @ 0x%08x+0x%x (0x%08x) in %a\n", + *UnwondStacksCount - 1, +
[edk2] [RFC v2 1/3] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 369 +++- 1 file changed, 367 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 65f0cff680..11cd7c9e1c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -242,6 +247,350 @@ DumpCpuContext ( ); } +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwondStacksCount Count of unwond stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwondStacksCount + ) +{ + // + // Check for proper stack pointer alignment + // + if (((UINTN)CurrentRsp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned stack pointer. \n"); +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwondStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + +// +// Point to next stack +// +CurrentRsp += CPU_STACK_ALIGNMENT; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID*EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + + // + // Set current RIP address + // + Rip = SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp = SystemContext.SystemContextX64->Rbp; + + // + // Check for proper frame pointer alignment + // + if (((UINTN)Rbp & (CPU_STACK_ALIGNMENT - 1)) != 0) { +InternalPrintMessage (" Unaligned frame pointer. \n"); +return; + } + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase = PeCoffSearchImageBase (Rip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find image module names. "); +return; + } + + // + // Get initial PE/COFF image's entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, ); + if (EFI_ERROR (Status)) { +EntryPoint = NULL; + } + + // + // Get file name and absolute path of initial PDB file + // + GetPdbFileName (ImageBase, , ); + + // + // Print out initial image module name (if any) + // + if (PdbAbsoluteFilePath != NULL) { +InternalPrintMessage ( + "\n%a (ImageBase=0x%016lx, EntryPoint=0x
[edk2] [RFC v2 2/3] UefiCpuPkg/CpuExceptionHandlerLib: Export GetPdbFileName()
This function will be used by both IA32 and X64 exception handling in order to print out image module names during stack unwinding. Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c | 60 +++- UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 14 + UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 59 --- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c index dbfaae1d30..f62ab8c48c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c @@ -54,6 +54,11 @@ CONST CHAR8 *mExceptionNameStr[] = { #define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *)) +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Get ASCII format string exception name by exception type. @@ -177,4 +182,57 @@ ReadAndVerifyVectorInfo ( VectorInfo ++; } return EFI_SUCCESS; -} \ No newline at end of file +} + +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h index 740a58828b..042207025e 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h @@ -288,5 +288,19 @@ CommonExceptionHandlerWorker ( IN EXCEPTION_HANDLER_DATA *ExceptionHandlerData ); +/** + Get absolute path and file name of PDB file in PE/COFF image. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ); + #endif diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 11cd7c9e1c..ace835c02c 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,11 +14,6 @@ #include "CpuExceptionCommon.h" -// -// Unknown PDB file name -// -GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; - /** Return address map of exception handler template so that C code can generate exception tables. @@ -247,60 +242,6 @@ DumpCpuContext ( ); } -/** - Get absolute path and file name of PDB file in PE/COFF image. - - @param[in] ImageBaseBase address of PE/COFF image. - @param[out] PdbAbsoluteFilePath Absolute path of PDB file. - @param[out] PdbFileName File name of PDB file. -**/ -STATIC -VOID -GetPdbFileName ( - IN UINTNImageBase, - OUT CHAR8**PdbAbsoluteFilePath, - OUT CHAR8**PdbFileName - ) -{ - VOID *PdbPointer; - CHAR8 *Str; - - // - // Get PDB file name from PE/COFF image - // - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); - if (PdbPointer == NULL) { -// -// No PDB file name found. Set it to an unknown file name.
Re: [edk2] 答复: 答复: [RFC 0/1] Stack trace support in X64 exception handling
Hi Fan, On 15/11/2017 11:21, Fan Jeff wrote: Paulo, I will try to validate my code firstly and try to integrate into your patch. OK. Thank you very much for the effort! Before my part ready, it’s also welcome if you or others provide yours own solution on X64 MSFT toolchain. Yes - that would be great. If I get this working on IA32 with GCC toolchain shortly, then I'll try to come up with a solution for MSVC. In my mind, IA32 arch should use the same solution with yours, have you tested your solution on IA32 arch with GCC toolchain? In theory, yes. :-) I haven't tested it yet, but I'll starting working it on now. BTW, do you think it's appropriate to just let you know that I pushed out another commit with IA32 support, or do you think it's better to send a v2 with it? Besides we shouldn't forget the suggestions from Andrew and Brian to validate the RIP and RSP values, as well as to have a kind of PCD to limit the number of stack frames printed out -- which I think that are really important even if unlikely. Thanks! Paulo Thanks! Jeff *From:* Paulo Alcantara <pca...@zytor.com> *Sent:* Tuesday, November 14, 2017 11:37:35 PM *To:* Fan Jeff; edk2-devel@lists.01.org *Cc:* Rick Bramley; Laszlo Ersek; Andrew Fish; Eric Dong *Subject:* Re: 答复: [edk2] [RFC 0/1] Stack trace support in X64 exception handling Hi Fan, On 14/11/2017 12:03, Fan Jeff wrote: Paul, I like this feature very much. Actually, I did some POC one year ago but I did finalize it. In my POC, I could use EBP to tack the stack frame on IAS32 arch. But for x64, I tried to use –keepexceptiontable flag to explain stack frame from the debug section of image. I may workson MSFT toolchain, but it did now work well for GCC toolchain. I think Eric could help to verify MSFT for your patch. If it works well, that’s will be great! Say again, I like this feature!!!:-) Cool! Your help would be really appreciable! If we get this working for X64 in both toolchains, that should be easy to port it to IA-32 as well. Thank you very much for willing to help on that. Paulo Thanks! Jeff *发件人: *Paulo Alcantara <mailto:pca...@zytor.com> *发送时间: *2017年11月14日21:23 *收件人: *edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> *抄送: *Rick Bramley <mailto:richard.bram...@hp.com>; Laszlo Ersek <mailto:ler...@redhat.com>; Andrew Fish <mailto:af...@apple.com>; Eric Dong <mailto:eric.d...@intel.com> *主题: *Re: [edk2] [RFC 0/1] Stack trace support in X64 exception handling Hi, On 14/11/2017 10:47, Paulo Alcantara wrote: Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. I've attached a file to show you how the trace would look like. Thanks! Paulo Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_x64 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (1): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC 0/1] Stack trace support in X64 exception handling
Hi, On 14/11/2017 15:41, Brian J. Johnson wrote: On 11/14/2017 11:23 AM, Andrew Fish wrote: On Nov 14, 2017, at 8:33 AM, Brian J. Johnson <brian.john...@hpe.com <mailto:brian.john...@hpe.com>> wrote: On 11/14/2017 09:37 AM, Paulo Alcantara wrote: Hi Fan, On 14/11/2017 12:03, Fan Jeff wrote: Paul, I like this feature very much. Actually, I did some POC one year ago but I did finalize it. In my POC, I could use EBP to tack the stack frame on IAS32 arch. But for x64, I tried to use –keepexceptiontable flag to explain stack frame from the debug section of image. I may workson MSFT toolchain, but it did now work well for GCC toolchain. I think Eric could help to verify MSFT for your patch. If it works well, that’s will be great! Say again, I like this feature!!!:-) Cool! Your help would be really appreciable! If we get this working for X64 in both toolchains, that should be easy to port it to IA-3 2 as well. Thank you very much for willing to help on that. Paulo Great feature! You do need some sort of sanity check on the RIP and RBP values, though, so if the stack gets corrupted or the RIP is nonsense from following a bad pointer, you don't start dereferencing garbage addresses and trigger an exception loop. Brian, This was a long time ago and my memory might be fuzzy I think we talked to some debugger folks about unwinding the stack and they mentioned it was common for the C runtime to have a return address or frame pointer have a zero value so the unwind logic knows when to stop. This is in addition to generic sanity checking. We got an extra push $0 added to the stack switch to help with stack unwind. https://github.com/tianocore/edk2/blob/master/MdePkg/Library/BaseLib/X64/SwitchStack.S If might be a good idea to have a PCD for the max number of stack frames to display as a fallback for the error check. For X64 you may also have to add a check for a non-cononical address as that will GP fault. Good idea. Regarding sanity checks: I've had good luck validating code locations (EIP values) by using a modified PeCoffExtraActionLib to track the top and bottom of the range where images have been loaded. (I've actually used two ranges: one for code executed from firmware space, and one for code executed from RAM.) I'm not sure offhand if there's a platform-independent way to validate stack pointer values. For most PC-like systems, just ensuring that it's larger than 1 or 2M (to avoid NULL pointers and the legacy spaces) and less than about 3G (or the low memory size, if that's known) may be enough to avoid an exception loop. Yeah, I agree with you guys. We certainly should be validating the RIP and RSP values and then avoiding the exception loop. For the RIP value, I think we should validate it in PeCoffSearchImageBase(), so if it's outside PE/COFF image's address space, then we should return an address of zero and no trace would be printed out. Since we already have a "SizeOfImage" field in PE/COFF Optional Header and it's available in the process' image, we might end up with checking whether RIP is between ImageBase through ImageBase + SizeOfImage - 1. For the RSP value, I have no idea :-) Thanks! Paulo Brian Thanks, Andrew Fish For at least some versions of Microsoft's IA32 compiler, it's possible to compile using EBP as a stack frame base pointer (like gcc) by using the "/Oy-" switch. The proposed unwind code should work in that case. The X64 compiler doesn't support this switch, though. AFAIK the only way to unwind the stack with Microsoft's X64 compilers is to parse the unwind info in the .pdata and .xdata sections. Genfw.exe usually strips those sections, but the "--keepexceptiontable" flag will preserve them, as Jeff pointed out. I've looked hard for open source code to decode them, but haven't found any, even though the format is well documented. And I haven't gotten around to writing it myself. I'd love it if someone could contribute the code! Another possibility is to use the branch history MSRs available on some x86-family processors. Recent Intel processors can use them as a stack, as opposed to a circular list, so they can record a backtrace directly. (I'm not familiar with AMD processors' capabilities.) You can enable call stack recording like this: #define LBR_ON_FLAG 0x0001 #define IA32_DEBUGCTL 0x1D9 #define CALL_STACK_SET_FLAG 0x3C4 #define CALL_STACK_CLR_FLAG 0xFC7 #define MSR_LBR_SELECT 0x1C8 // // Enable branch recording // LbControl = AsmReadMsr64 ((UINT32)IA32_DEBUGCTL); LbControl |= LBR_ON_FLAG; AsmWriteMsr64 ((UINT32)IA32_DEBUGCTL, LbControl); // // Configure for call stack // LbSelect = AsmReadMsr64 ((UINT32)MSR_LBR_SELECT); LbSelect &= CALL_STACK_CLR_FLAG; LbSelect |= CALL_STACK_SET_FLAG; AsmWriteMsr64((UINT32)MSR_LBR_SELECT, LbSelect); The EIP/RIP values are lo
Re: [edk2] [PATCH 0/2] Refine UDF related codes
Hi Hao, On 14/11/2017 05:51, Hao Wu wrote: The series will do the following refinements: a. Merge the discovery of the El Torito feature on CD/DVD media into the detect of UDF; b. Avoid possible loss track of the allocated buffer pointer in UdfDxe. Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Eric Dong <eric.d...@intel.com> Hao Wu (2): MdeModulePkg/PartitionDxe: Merge the discovery of ElTorito into UDF MdeModulePkg/UdfDxe: Avoid possible loss track of allocated buffer MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c | 7 +++ MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 17 + MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 12 +++- 3 files changed, 27 insertions(+), 9 deletions(-) Looks good to me. Thanks for fixing and testing it! Reviewed-by: Paulo Alcantara <pca...@zytor.com> Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] 答复: [RFC 0/1] Stack trace support in X64 exception handling
Hi Fan, On 14/11/2017 12:03, Fan Jeff wrote: Paul, I like this feature very much. Actually, I did some POC one year ago but I did finalize it. In my POC, I could use EBP to tack the stack frame on IAS32 arch. But for x64, I tried to use –keepexceptiontable flag to explain stack frame from the debug section of image. I may workson MSFT toolchain, but it did now work well for GCC toolchain. I think Eric could help to verify MSFT for your patch. If it works well, that’s will be great! Say again, I like this feature!!!:-) Cool! Your help would be really appreciable! If we get this working for X64 in both toolchains, that should be easy to port it to IA-32 as well. Thank you very much for willing to help on that. Paulo Thanks! Jeff *发件人: *Paulo Alcantara <mailto:pca...@zytor.com> *发送时间: *2017年11月14日21:23 *收件人: *edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> *抄送: *Rick Bramley <mailto:richard.bram...@hp.com>; Laszlo Ersek <mailto:ler...@redhat.com>; Andrew Fish <mailto:af...@apple.com>; Eric Dong <mailto:eric.d...@intel.com> *主题: *Re: [edk2] [RFC 0/1] Stack trace support in X64 exception handling Hi, On 14/11/2017 10:47, Paulo Alcantara wrote: Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. I've attached a file to show you how the trace would look like. Thanks! Paulo Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_x64 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (1): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [RFC 1/1] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
Hi Andrew, On 14/11/2017 12:01, Andrew Fish wrote: C> Paulo, Cool feature. How does this code deal with VC++ that code does not store the frame pointer and requires symbols to unwind. I haven't tested in with MSVC, so I'd hope to get some help from Intel's guys to help supporting and testing it :-) Regarding the symbols, I performed some tests by writing a userspace PE/COFF application [1] and tried to: (a) handle the RUNTIME_FUNCTION entries in exception table (.pdata section) to find the function starting address and then its respective symbol name in COFF symbol table. (b) Walk through UNWIND_INFO entries in .xdata section to figure out which CPU register a function used as a frame pointer or if it didn't use any at all. The problem I had with (a) was that the COFF symbol table is not mapped directory into the image's address space -- that is, the "PointerToSymbolTable" in File Header *should* be 0 as per PE/COFF format specific when handling an executable file rather a object file. Additionally, if it's non-zero, it contains a file offset rather than a RVA address, so impossible to parse it at runtime. In (b), I realized that the CodeView format data in debug directory should be kept in a separate file (PDB file?) and they aren't mapped into image's address space as well. I don't have so much experience with PE/COFF format, so please correct me if I'm mistaken. IMHO, there should be exist a function like AsmGetFrameAddress() and/or AsmGetStackAddress() which would get implemented for both GCC and MSVC toolchains. Thank you very much for your comments! Also on the page fault you can print the fault address since it is in CR2. Good point! We should also do that. It should be possible to post process the text file and make a symbolicated backtrace. Yes. Thanks! Paulo Thanks, Andrew Fish On Nov 14, 2017, at 4:47 AM, Paulo Alcantara <pca...@zytor.com> wrote: This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 65f0cff680..7048247be3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -243,6 +248,325 @@ DumpCpuContext ( } /** + Dump stack contents. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwondStacksCount Count of unwond stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwondStacksCount + ) +{ + if (UnwondStacksCount == 0) { +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwondStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx:
Re: [edk2] [RFC 0/1] Stack trace support in X64 exception handling
Hi, On 14/11/2017 10:47, Paulo Alcantara wrote: Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. I've attached a file to show you how the trace would look like. Thanks! Paulo Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_x64 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (1): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) X64 Exception Type - 0E(#PF - Page-Fault) CPU Apic ID - ExceptionData - 0002 I:0 R:0 U:0 W:1 P:0 PK:0 S:0 RIP - 7E510F7F, CS - 0038, RFLAGS - 00010202 RAX - , RCX - 7EA01318, RDX - 7F6EE018 RBX - 00810248, RSP - 7F762C70, RBP - 7F762CB0 RSI - 0007, RDI - 7EA01418 R8 - 7E513A88, R9 - 7EA01798, R10 - 0036 R11 - 00D7, R12 - , R13 - R14 - , R15 - DS - 0030, ES - 0030, FS - 0030 GS - 0030, SS - 0030 CR0 - 80010033, CR2 - , CR3 - 7F701000 CR4 - 0668, CR8 - DR0 - , DR1 - , DR2 - DR3 - , DR6 - 0FF0, DR7 - 0400 GDTR - 7F6EEA98 0047, LDTR - IDTR - 7EEF2018 0FFF, TR - FXSAVE_STATE - 7F7628D0 Back trace: 0 0x7E510F7F @ 0x7E509000+0x7F7E (0x7F762CB0) in PartitionDxe.dll 1 0x7E51135D @ 0x7E509000+0x835C (0x7F762CE0) in PartitionDxe.dll 2 0x7E50C116 @ 0x7E509000+0x3115 (0x7F762D20) in PartitionDxe.dll 3 0x7F776972 @ 0x7E509000+0x126D971 (0x7F762DB0) in PartitionDxe.dll 4 0x7F78EE08 @ 0x7E509000+0x1285E07 (0x7F762E30) in PartitionDxe.dll 5 0x7F791343 @ 0x7E509000+0x1288342 (0x7F762F60) in PartitionDxe.dll 6 0x7F791AC7 @ 0x7E509000+0x1288AC6 (0x7F762F90) in PartitionDxe.dll 7 0x7F767DDB @ 0x7E509000+0x125EDDA (0x7F762FC0) in PartitionDxe.dll 8 0x7F7DF75F @ 0x7E509000+0x12D675E (0x7B7DC840) in PartitionDxe.dll 9 0x7F7E5546 @ 0x7E509000+0x12DC545 (0x7B7DC8C0) in PartitionDxe.dll 10 0x7F7E4312 @ 0x7E509000+0x12DB311 (0x7B7DCA30) in PartitionDxe.dll 11 0x7F7F0DB9 @ 0x7E509000+0x12E7DB8 (0x7B7DCF80) in PartitionDxe.dll 12 0x008286E9 @ 0x00820140+0x85A8 (0x7B7DD4D0) in PeiCore.dll 13 0x0083092F @ 0x00820140+0x107EE (0x00817600) in PeiCore.dll 14 0x00831574 @ 0x00820140+0x11433 (0x008176D0) in PeiCore.dll 15 0x00828D9B @ 0x00820140+0x8C5A (0x00817C20) in PeiCore.dll 16 0x0083238A @ 0x00820140+0x12249 (0x00817C50) in PeiCore.dll 17 0x00824312 @ 0x00820140+0x41D1 (0x00817C80) in PeiCore.dll 18 0xFFFD4291 @ 0x00820140+0xFF7B4150 (0x00817CE0) in PeiCore.dll 19 0xFFFCF578 @ 0x00820140+0xFF7AF437 (0x00817D10) in PeiCore.dll 20 0xFFFD422C @ 0x00820140+0xFF7B40EB (0x00817FD0) in PeiCore.dll 21 0xFFFD4489 @ 0x00820140+0xFF7B4348 (0xFFFCC000) in PeiCore.dll PartitionDxe.dll (ImageBase=0x7E509000, EntryPoint=0x7E50C01F): /home/pcacjr/src/edk2.git/Build/OvmfX64/NOOPT_GCC5/X64/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe/DEBUG/PartitionDxe.dll PeiCore.dll (ImageBase=0x00820140, EntryPoint=0x008242EC): /home/pcacjr/src/edk2.git/Build/OvmfX64/NOOPT_GCC5/X64/MdeModulePkg/Core/Pei/PeiMain/DEBUG/PeiCore.dll Stack dump: 0x7F762C70: 7E5137E0 0x7F762C80: 7E513A88 0100 0x7F762C90: 7F762CB0 0x
[edk2] [RFC 0/1] Stack trace support in X64 exception handling
Hi, This series adds stack trace support during a X64 CPU exception. Informations like back trace, stack contents and image module names (that were part of the call stack) will be dumped out. We already have such support in ARM/AArch64 (IIRC) exception handling (thanks to Ard), and then I thought we'd also deserve it in X64 and IA-32 platforms. What do you think guys? BTW, I've tested this only with OVMF (X64 only), using: - gcc-6.3.0, GCC5, NOOPT Any other tests would be really appreciable. Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: stacktrace_x64 Cc: Rick Bramley <richard.bram...@hp.com> Cc: Andrew Fish <af...@apple.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (1): UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [RFC 1/1] UefiCpuPkg/CpuExceptionHandlerLib/X64: Add stack trace support
This patch adds stack trace support during a X64 CPU exception. It will dump out back trace, stack contents as well as image module names that were part of the call stack. Contributed-under: TianoCore Contribution Agreement 1.1 Cc: Eric Dong <eric.d...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 344 +++- 1 file changed, 342 insertions(+), 2 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c index 65f0cff680..7048247be3 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c @@ -14,6 +14,11 @@ #include "CpuExceptionCommon.h" +// +// Unknown PDB file name +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mUnknownPdbFileName = ""; + /** Return address map of exception handler template so that C code can generate exception tables. @@ -243,6 +248,325 @@ DumpCpuContext ( } /** + Dump stack contents. + + @param[in] ImageBaseBase address of PE/COFF image. + @param[out] PdbAbsoluteFilePath Absolute path of PDB file. + @param[out] PdbFileName File name of PDB file. +**/ +STATIC +VOID +GetPdbFileName ( + IN UINTNImageBase, + OUT CHAR8**PdbAbsoluteFilePath, + OUT CHAR8**PdbFileName + ) +{ + VOID *PdbPointer; + CHAR8 *Str; + + // + // Get PDB file name from PE/COFF image + // + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)ImageBase); + if (PdbPointer == NULL) { +// +// No PDB file name found. Set it to an unknown file name. +// +*PdbFileName = (CHAR8 *)mUnknownPdbFileName; +if (PdbAbsoluteFilePath != NULL) { + *PdbAbsoluteFilePath = NULL; +} + } else { +// +// Get file name portion out of PDB file in PE/COFF image +// +Str = (CHAR8 *)((UINTN)PdbPointer + +AsciiStrLen ((CHAR8 *)PdbPointer) - sizeof *Str); +for (; *Str != '/' && *Str != '\\'; Str--) { + ; +} + +// +// Set PDB file name (also skip trailing path separator: '/' or '\\') +// +*PdbFileName = Str + 1; + +if (PdbAbsoluteFilePath != NULL) { + // + // Set absolute file path of PDB file + // + *PdbAbsoluteFilePath = PdbPointer; +} + } +} + +/** + Dump stack contents. + + @param[in] CurrentRsp Current stack pointer address. + @param[in] UnwondStacksCount Count of unwond stack frames. +**/ +STATIC +VOID +DumpStackContents ( + IN UINT64 CurrentRsp, + IN INTNUnwondStacksCount + ) +{ + if (UnwondStacksCount == 0) { +return; + } + + // + // Dump out stack contents + // + InternalPrintMessage ("\nStack dump:\n"); + while (UnwondStacksCount-- > 0) { +InternalPrintMessage ( + "0x%016lx: %016lx %016lx\n", + CurrentRsp, + *(UINT64 *)CurrentRsp, + *(UINT64 *)((UINTN)CurrentRsp + 8) + ); + +// +// As per Microsoft x64 ABI, the stack pointer must be aligned on a 16 byte +// boundary. +// +CurrentRsp = CurrentRsp + 16; + } +} + +/** + Dump all image module names from call stack. + + @param[in] SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +STATIC +VOID +DumpImageModuleNames ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + EFI_STATUS Status; + UINT64 Rip; + UINTN ImageBase; + VOID*EntryPoint; + CHAR8 *PdbAbsoluteFilePath; + CHAR8 *PdbFileName; + UINT64 Rbp; + + // + // Set current RIP address + // + Rip = SystemContext.SystemContextX64->Rip; + + // + // Set current frame pointer address + // + Rbp = SystemContext.SystemContextX64->Rbp; + + // + // Get initial PE/COFF image base address from current RIP + // + ImageBase = PeCoffSearchImageBase (Rip); + if (ImageBase == 0) { +InternalPrintMessage (" Could not find image module names. "); +return; + } + + // + // Get initial PE/COFF image's entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)ImageBase, ); + if (EFI_ERROR (Status)) { +EntryPoint = NULL; + } + + // + // Get file name and absolute path of initial PDB file + // + GetPdbFileName (ImageBase, , ); + + // + // Print out initial image module name (if any) + // + if (PdbAbsoluteFilePath != NULL) { +InternalPrintMessage ( + "\n%a (ImageBase=0x%016lx, EntryPoint=0x%016lx):\n", + PdbFileName, + ImageBase, + (UINTN)EntryPoint + ); +InternalPrintMessage ("%a\n", PdbAbsoluteFilePath); + } + + // + // Walk through call stack and find next module names + // + for (;;) { +// +// Set RIP with return address from current stack frame +// +Rip = *(UINT64 *)((UINTN)Rbp + 8); + +
[edk2] [PATCH] ShellPkg: Fix type mismatch with GCC
This patch fixes the following warning reported by GCC 6.3: /home/pcacjr/src/edk2.git/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c:271:1: warning: type of ‘InternalCharToUpper’ does not match original decl aration [-Wlto-type-mismatch] InternalCharToUpper ( ^ /home/pcacjr/src/edk2.git/MdePkg/Library/BaseLib/String.c:555:1: note: ‘InternalCharToUpper’ was previously declared here InternalCharToUpper ( ^ Cc: Jaben Carsey <jaben.car...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pa...@hp.com> --- ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c index 7948e53cfc..bab6631e15 100644 --- a/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c +++ b/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c @@ -268,6 +268,7 @@ VerifyIntermediateDirectories ( @return Char as an upper case character. **/ CHAR16 +EFIAPI InternalCharToUpper ( IN CONST CHAR16Char ); -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on certain CD/DVD medias
Hi Laszlo, On 13/10/2017 10:37, Laszlo Ersek wrote: Hi Paulo, On 10/13/17 15:24, Paulo Alcantara wrote: REF: https://bugzilla.tianocore.org/show_bug.cgi?id=725 Thank you for the patch. Some meta comments: When you post a patch for a TianoCore BZ, can you please (1) flip the TianoCore BZ in question to status IN_PROGRESS, (2) add a comment to the BZ, with a link to the patch in the mailing list archive <https://lists.01.org/pipermail/edk2-devel/> -- in this case, the link would be: https://lists.01.org/pipermail/edk2-devel/2017-October/016031.html (3) optionally, assign the BZ to yourself? In particular step (2) is very helpful when a BZ takes several iterations of a patch set, and later someone would like to review the evolution of the patches. (It's not necessary to comment at length in the BZ about the patch set versions -- that's what the patch set cover letters are for --, capturing the archive links is enough and helpful.) Finally, when the patch is applied and the BZ is fixed, it's best to: (4) kick the BZ to RESOLVED|FIXED, and (5) add a comment about the git commit hash of the patch. Sure. I'll make sure to follow those steps carefully next time. Thanks! I've just did (1), (2) and (3). Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH] MdeModulePkg/PartitionDxe: Fix UDF fs access on certain CD/DVD medias
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=725 Historically many drives or medias do not correctly return their value for block N - which is also referred as last addressable/recorded block. When they do so, there is still a problem when relying on last recorded block number returned by SCSI commands READ CAPACITY and READ TRACK INFORMATION - that is, between block 0 and block N there may be unwritten blocks which are located outside any track. That said, the Partition driver was unable to find AVDP at block N on certain medias that do not either return or report their last recorded block number correctly. Apparently there is no official or correct way to find the correct block number, however tools like the Philips UDF Conformance Tool (udf_test) apply a correction by searching for an AVDP or VAT in blocks N through N-456 -- this can be observed by looking at the log reported by udf_test on those CD/DVD medias. So, if the AVDP or VAT is found, then it sets the last recorded block number to where AVDP or VAT was located. With the below setence in UDF 2.60, 6.13.2.2 Background Physical Formatting: "... the second AVDP must be recorded after the Background physical Formatting has been finished..." Implies that the last recorded block is the one where second AVDP was recorded. This patch implements a similar way to correct the last recorded block number by searching for last AVDP in blocks N-1 through N-512 on those certain medias, as well as ensure a minimum number of 2 AVDPs found as specified by ECMA 167 and UDF 2.60 specifications. Cc: Hao Wu <hao.a...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Eric Dong <eric.d...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Hao Wu <hao.a...@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 254 1 file changed, 201 insertions(+), 53 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 8aee30c759..7eee748958 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -14,6 +14,8 @@ #include "Partition.h" +#define MAX_CORRECTION_BLOCKS_NUM 512u + // // C5BD4D42-1A76-4996-8956-73CDA326CD0A // @@ -48,61 +50,199 @@ UDF_DEVICE_PATH gUdfDevicePath = { /** Find the anchor volume descriptor pointer. - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. - @param[out] AnchorPoint Anchor volume descriptor pointer. + @param[in] BlockIo BlockIo interface. + @param[in] DiskIoDiskIo interface. + @param[out] AnchorPoint Anchor volume descriptor pointer. + @param[out] LastRecordedBlock Last recorded block. - @retval EFI_SUCCESS Anchor volume descriptor pointer found. - @retval EFI_VOLUME_CORRUPTEDThe file system structures are corrupted. - @retval other Anchor volume descriptor pointer not found. + @retval EFI_SUCCESS Anchor volume descriptor pointer found. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval other Anchor volume descriptor pointer not found. **/ EFI_STATUS FindAnchorVolumeDescriptorPointer ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, - OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint + OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, + OUT EFI_LBA *LastRecordedBlock ) { - EFI_STATUS Status; - UINT32 BlockSize; - EFI_LBA EndLBA; - EFI_LBA DescriptorLBAs[4]; - UINTN Index; - UDF_DESCRIPTOR_TAG *DescriptorTag; + EFI_STATUSStatus; + UINT32BlockSize; + EFI_LBA EndLBA; + UDF_DESCRIPTOR_TAG*DescriptorTag; + UINTN AvdpsCount; + UINTN Size; + UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoints; + INTN Index; + UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPointPtr; + EFI_LBA LastAvdpBlockNum; + // + // UDF 2.60, 2.2.3 Anchor Volume Descriptor Pointer + // + // An Anchor Volume Descriptor Pointer structure shall be recorded in at + // least 2 of the following 3 locations on the media: Logical Sector 256, + // N - 256 or N, where N is the last *addressable* sector of a volume. + // + // To figure out what logical sector N is, the SCSI commands READ CAPACITY and + // READ TRACK INFORMATION are used, however many drives or medias report t
Re: [edk2] [PATCH] MdeModulePkg/UdfDxe: Resolve potential NULL pointer dereference
On September 25, 2017 10:36:48 PM GMT-03:00, Hao Wu <hao.a...@intel.com> wrote: >Within function GetAllocationDescriptorLsn(): > >The call to GetPdFromLongAd() may return NULL and it will be later >dereferenced in GetShortAdLsn(). > >This commit adds ASSERT to resolve the potential NULL pointer >dereference. > >Cc: Paulo Alcantara <pca...@zytor.com> >Cc: Ruiyu Ni <ruiyu...@intel.com> >Cc: Star Zeng <star.z...@intel.com> >Cc: Eric Dong <eric.d...@intel.com> >Contributed-under: TianoCore Contribution Agreement 1.1 >Signed-off-by: Hao Wu <hao.a...@intel.com> >--- > MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 7 ++- > 1 file changed, 6 insertions(+), 1 deletion(-) > >diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >index b336ffc553..e048d95d31 100644 >--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >@@ -748,12 +748,17 @@ GetAllocationDescriptorLsn ( > IN VOID*Ad > ) > { >+ UDF_PARTITION_DESCRIPTOR *PartitionDesc; >+ > if (RecordingFlags == LongAdsSequence) { >return GetLongAdLsn (Volume, (UDF_LONG_ALLOCATION_DESCRIPTOR *)Ad); > } else if (RecordingFlags == ShortAdsSequence) { >+PartitionDesc = GetPdFromLongAd (Volume, ParentIcb); >+ASSERT (PartitionDesc != NULL); >+ > return GetShortAdLsn ( > Volume, >- GetPdFromLongAd (Volume, ParentIcb), >+ PartitionDesc, > (UDF_SHORT_ALLOCATION_DESCRIPTOR *)Ad > ); > } Reviewed-by: Paulo Alcantara <pca...@zytor.com> Thanks! Paulo -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH v4 2/2] MdeModulePkg/UDF: Fix creation of UDF logical partition
Do not reserve entire block device size for an UDF file system - instead, reserve the appropriate space (UDF logical volume space) for it. Additionally, only create a logical partition for UDF logical volumes that are currently supported by EDK2 UDF file system implementation. For instance, an UDF volume with a single LVD and a single Physical (Type 1) Partition will be supported. Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Reported-by: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> Tested-by: Hao Wu <hao.a...@intel.com> Build-tested-by: Laszlo Ersek <ler...@redhat.com> Reviewed-by: Star Zeng <star.z...@intel.com> Build-tested-by: Star Zeng <star.z...@intel.com> Build-tested-by: Paulo Alcantara <pa...@hp.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 366 ++-- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 ++--- 5 files changed, 606 insertions(+), 568 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 609f56cef6..8aee30c759 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint ) { - EFI_STATUS Status; - UINT32 BlockSize; - EFI_LBA EndLBA; - EFI_LBA DescriptorLBAs[4]; - UINTN Index; + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBA EndLBA; + EFI_LBA DescriptorLBAs[4]; + UINTN Index; + UDF_DESCRIPTOR_TAG *DescriptorTag; BlockSize = BlockIo->Media->BlockSize; EndLBA = BlockIo->Media->LastBlock; @@ -88,10 +89,13 @@ FindAnchorVolumeDescriptorPointer ( if (EFI_ERROR (Status)) { return Status; } + +DescriptorTag = >DescriptorTag; + // // Check if read LBA has a valid AVDP descriptor. // -if (IS_AVDP (AnchorPoint)) { +if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) { return EFI_SUCCESS; } } @@ -102,23 +106,18 @@ FindAnchorVolumeDescriptorPointer ( } /** - Check if block device supports a valid UDF file system as specified by OSTA - Universal Disk Format Specification 2.60. + Find UDF volume identifiers in a Volume Recognition Sequence. - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. + @param[in] BlockIo BlockIo interface. + @param[in] DiskIo DiskIo interface. - @retval EFI_SUCCESS UDF file system found. - @retval EFI_UNSUPPORTED UDF file system not found. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of - resources. + @retval EFI_SUCCESS UDF volume identifiers were found. + @retval EFI_NOT_FOUND UDF volume identifiers were not found. + @retval other Failed to perform disk I/O. **/ EFI_STATUS -SupportUdfFileSystem ( +FindUdfVolumeIdentifiers ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo ) @@ -128,7 +127,6 @@ SupportUdfFileSystem ( UINT64EndDiskOffset; CDROM_VOLUME_DESCRIPTOR VolDescriptor; CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor; - UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; ZeroMem ((VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)); @@ -167,7 +165,7 @@ SupportUdfFileSystem ( (CompareMem ((VOID *), (VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) { - return EFI_UNSUPPORTED; + return EFI_NOT_FOUND; } } @@ -176,7 +174,7 @@ SupportUdfFileSystem ( // Offset += UDF_LOGICAL_SECTOR_SIZE; if (Offset >= EndDiskOffset) { -return EFI_UNSUPPORTED; +return EFI_NOT_FOUND; } Status = DiskIo->ReadDisk ( @@ -196,7 +194,7 @@ SupportUdfFileSystem ( (CompareMem ((VOID *)VolDescriptor.Unknown.Id, (VOID *)UDF_NSR3_IDENTIFIER, sizeof (VolDescriptor.Unknown.Id)) != 0)) { -return EFI_UNSUPPORTED; +return EFI_NOT_FOUND; } // @@ -204,7 +202,7 @@ SupportUdfFileSystem ( // Offset += UDF_LOGIC
[edk2] [PATCH v4 1/2] MdePkg: Add UDF volume structure definitions
This patch adds a few more UDF volume structures in order to detect an UDF file system which is supported by current EDK2 UDF file system implementation in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> Build-tested-by: Laszlo Ersek <ler...@redhat.com> Reviewed-by: Star Zeng <star.z...@intel.com> Tested-by: Hao Wu <hao.a...@intel.com> Build-tested-by: Star Zeng <star.z...@intel.com> Build-tested-by: Paulo Alcantara <pa...@hp.com> --- MdePkg/Include/IndustryStandard/Udf.h | 97 +++- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..5806560aee 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -24,11 +24,22 @@ #define UDF_LOGICAL_SECTOR_SIZE ((UINT64)(1ULL << UDF_LOGICAL_SECTOR_SHIFT)) #define UDF_VRS_START_OFFSET ((UINT64)(16ULL << UDF_LOGICAL_SECTOR_SHIFT)) -#define _GET_TAG_ID(_Pointer) \ - (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) - -#define IS_AVDP(_Pointer) \ - ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +typedef enum { + UdfPrimaryVolumeDescriptor = 1, + UdfAnchorVolumeDescriptorPointer = 2, + UdfVolumeDescriptorPointer = 3, + UdfImplemenationUseVolumeDescriptor = 4, + UdfPartitionDescriptor = 5, + UdfLogicalVolumeDescriptor = 6, + UdfUnallocatedSpaceDescriptor = 7, + UdfTerminatingDescriptor = 8, + UdfLogicalVolumeIntegrityDescriptor = 9, + UdfFileSetDescriptor = 256, + UdfFileIdentifierDescriptor = 257, + UdfAllocationExtentDescriptor = 258, + UdfFileEntry = 261, + UdfExtendedFileEntry = 266, +} UDF_VOLUME_DESCRIPTOR_ID; #pragma pack(1) @@ -49,12 +60,88 @@ typedef struct { } UDF_EXTENT_AD; typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + union { +// +// Domain Entity Identifier +// +struct { + UINT16 UdfRevision; + UINT8 DomainFlags; + UINT8 Reserved[5]; +} Domain; +// +// UDF Entity Identifier +// +struct { + UINT16 UdfRevision; + UINT8 OSClass; + UINT8 OSIdentifier; + UINT8 Reserved[4]; +} Entity; +// +// Implementation Entity Identifier +// +struct { + UINT8 OSClass; + UINT8 OSIdentifier; + UINT8 ImplementationUseArea[6]; +} ImplementationEntity; +// +// Application Entity Identifier +// +struct { + UINT8 ApplicationUseArea[8]; +} ApplicationEntity; +// +// Raw Identifier Suffix +// +struct { + UINT8 Data[8]; +} Raw; + } Suffix; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { UDF_DESCRIPTOR_TAG DescriptorTag; UDF_EXTENT_AD MainVolumeDescriptorSequenceExtent; UDF_EXTENT_AD ReserveVolumeDescriptorSequenceExtent; UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + #pragma pack() #endif -- 2.13.3.windows.1 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH v4 0/2] UDF partition driver fix
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707 Hi, This patchset fixes a bug in Partition driver that created UDF logical partitions by using entire block device space and thus polluting protocol database with broken handles. v1->v2: - Followed Laszlo's suggestions to submit a proper patchset. Thanks! - As I'm still waiting for Ruiyu and Star to test this fix, I took advantage of it and did some code cleanups :-) v2->v3: - Followed Ruiyu's suggestions to improve code and add additional checks for ensuring a valid UDF file system and supported by current EDK2 UDF file system implementation. Also run Ecc.py to make sure the files I touched did not break EDK2 C Coding Style, as well as PatchCheck.py for mal-formed patches. v3->v4: - Change 2/2's title as suggested by Star. - Remove UDF_TAG_ID() and refactor out UDF_ENTITY_ID structure as suggested by Ruiyu. - Tested build with VS2015 toolchain. I've had a chance to test these changes with my 32GiB USB stick and formatted it on Windows 10 with `format` command. The UDF revisions I tested (by specifying it with "/R:revision") were 1.02, 1.50, 2.00, 2.01 (default) and 2.50. They all worked except the 2.50 revision which adds a Type 2 (Metadata) Partition and it's not supported by current EDK2 UDF implementation -- which handles only Type 1 (Physical) Partitions. The UDF 2.60 revision I tested with the usual `sudo mkudffs -b 512 --media-type=hd /dev/sdX` command in Linux. Remember, the *officially* supported revision is 2.60, however all revisions use the same volume structures as defined by ECMA 167 specification, and they usually differ from each other by means of new optional features, so that's why all those revisions worked with this implementation. Well, at least this what I understood when looking at the specifications. Please correct me if I'm wrong. Please, test building these changes in toolchains other than GCC and make sure they don't break the world :-) Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix-v4 Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Jiewen Yao <jiewen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Ruiyu Ni <ruiyu...@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (2): MdePkg: Add UDF volume structure definitions MdeModulePkg/UDF: Fix creation of UDF logical partition MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 366 ++-- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 ++--- MdePkg/Include/IndustryStandard/Udf.h | 97 ++- 6 files changed, 698 insertions(+), 573 deletions(-) -- 2.13.3.windows.1 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v3 1/2] MdePkg: Add UDF volume structure definitions
Ruiyu, On 9/21/2017 11:50 PM, Ni, Ruiyu wrote: Paulo, Comments below: #define UDF_TAG_ID(_Tag) \ (UDF_VOLUME_DESCRIPTOR_ID)((_Tag)->TagIdentifier) 1. I prefer to remove the UDF_TAG_ID macro. Adding type-cast to get TAG_ID is very straightforward. Right. I'll remove it. #define UDF_LVD_REVISION(_Lv) \ *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix typedef struct { UINT8 Flags; UINT8 Identifier[23]; UINT8 IdentifierSuffix[8]; } UDF_ENTITY_ID; 2. Entity structure is defined by ECMA-167 spec and re-used by UDF spec. I think since we are creating UDF structure in udf.h, how about using the below structure layout and removing the UDF_LVD_REVISION macro: Typedef struct { UINT8 Flags; UINT8 Identifier[23]; UINT16 UdfRevision; UINT8 DomainFlags; UINT8 Reserved[5]; } UDF_ENTITY_ID; Much better! Thanks for looking into that. The UDF 2.60 specification says: > UDF classifies Entity Identifiers into 4 separate types. Each type has > its own Suffix Type for the Identifier Suffix field. The 4 types are: > > Domain Entity Identifiers with a Domain Identifier Suffix > UDF Entity Identifierswith a UDF Identifier Suffix > Implementation Entity Identifiers with an Implementation Identifier Suffix > Application Entity Identifierswith an Application Identifier Suffix Given that, I think an union would be more appropriate. E.g., typedef struct { UINT8 Flags; UINT8 Identifier[23]; union { struct { UINT16 UdfRevision; UINT8 DomainFlags; UINT8 Reversed[5]; } DomainIdentifier; struct { UINT16 UdfRevision; UINT8 OSClass; UINT8 OSIdentifier; UINT8 Reserved[4]; } EntityIdentifier; struct { UINT8 OSClass; UINT8 OSIdentifier; UINT8 ImplementationUseArea[6]; } ImplementationEntityIdentifier; struct { UINT8 ApplicationUseArea[8]; } ApplicationEntityIdentifier; UINT8 IdentifierSuffix[8]; }; } UDF_ENTITY_ID; Do you agree with me? Or that wouldn't be necessary? Thanks! Paulo I am not sure if there are other structures that are defined in ECMA spec and re-used by UDF spec. I think we can apply the similar rules to those structures as well. Thanks/Ray -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Thursday, September 21, 2017 2:16 AM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Kinney, Michael D <michael.d.kin...@intel.com>; Gao, Liming <liming@intel.com>; Laszlo Ersek <ler...@redhat.com>; Ni, Ruiyu <ruiyu...@intel.com> Subject: [PATCH v3 1/2] MdePkg: Add UDF volume structure definitions This patch adds a few more UDF volume structures in order to detect an UDF file system which is supported by current EDK2 UDF file system implementation in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 ++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..002e87e150 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -24,11 +24,28 @@ #define UDF_LOGICAL_SECTOR_SIZE ((UINT64)(1ULL << UDF_LOGICAL_SECTOR_SHIFT)) #define UDF_VRS_START_OFFSET ((UINT64)(16ULL << UDF_LOGICAL_SECTOR_SHIFT)) -#define _GET_TAG_ID(_Pointer) \ - (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +typedef enum { + UdfPrimaryVolumeDescriptor = 1, + UdfAnchorVolumeDescriptorPointer = 2, + UdfVolumeDescriptorPointer = 3, + UdfImplemenationUseVolumeDescriptor = 4, + UdfPartitionDescriptor = 5, + UdfLogicalVolumeDescriptor = 6, + UdfUnallocatedSpaceDescriptor = 7, + UdfTerminatingDescriptor = 8, + UdfLogicalVolumeIntegrityDescriptor = 9, + UdfFileSetDescriptor = 256, + UdfFileIdentifierDescriptor = 257, + UdfAllocationExtentDescriptor = 258, + UdfFileEntry = 261, + UdfExtendedFileEntry = 266, +} UDF_VOLUME_DESCRIPTOR_ID; -#define IS_AVDP(_Pointer) \ - ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define UDF_TAG_ID(_Tag) \ + (UDF_VOLUME_DESCRIPTOR_ID)((_Tag)->TagIdentifier) + +#define UDF_LVD_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix #pragma pack(1) @@ -49,12 +66,50 @@ typedef struct { } UDF_EXTENT_AD; typedef struct { + UINT8 CharacterSetType; + UINT8 Charact
Re: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
On Thu, Sep 21, 2017 at 10:52 AM, Paulo Alcantara <pca...@zytor.com> wrote: > > > On September 21, 2017 10:47:07 AM GMT-03:00, "Zeng, Star" > <star.z...@intel.com> wrote: >>Does it have functional impact? > > Nope. When Partition driver walks the partition detect routine table, it > executes each routine and then checks for EFI_NO_MEDIA and EFI_MEDIA_CHANGED > only. So, the child handle is installed and the EFI_NOT_FOUND is a no-op in > that case. BTW, I performed a quick test with UdfDxe enabled and disabled in OVMF and the removal did not seem to break or change any behavior. Thanks! Paulo > > Thanks! > Paulo > >> >>Thanks, >>Star >>-Original Message- >>From: Paulo Alcantara [mailto:pca...@zytor.com] >>Sent: Thursday, September 21, 2017 9:29 PM >>To: Wu, Hao A <hao.a...@intel.com>; edk2-devel@lists.01.org >>Cc: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com>; >>Dong, Eric <eric.d...@intel.com>; Zeng, Star <star.z...@intel.com> >>Subject: RE: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >>creation of UDF logical partition >> >> >> >>On September 21, 2017 9:44:10 AM GMT-03:00, "Wu, Hao A" >><hao.a...@intel.com> wrote: >>>One small comment, within function PartitionInstallUdfChildHandles(): >>> >>> ... >>> // >>> // Install partition child handle for UDF file system >>> // >>> Status = PartitionInstallChildHandle ( >>>... >>>); >>>if (!EFI_ERROR (Status)) { <- Is this a typo? "if (EFI_ERROR >>>(Status)) {" >>>Status = EFI_NOT_FOUND; >>> } >> >>Yes, it is. Good catch! Could you please fix that for me by removing >>the if condition? Otherwise I can send a v4 later with that. >> >>Thanks! >>Paulo >> >>> >>> >>>Best Regards, >>>Hao Wu >>> >>> >>>> -Original Message- >>>> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf >>>Of Paulo >>>> Alcantara >>>> Sent: Thursday, September 21, 2017 2:16 AM >>>> To: edk2-devel@lists.01.org >>>> Cc: Ni, Ruiyu; Laszlo Ersek; Dong, Eric; Zeng, Star >>>> Subject: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >>>creation of >>>> UDF logical partition >>>> >>>> Do not reserve entire block device size for an UDF file system - >>>> instead, reserve the appropriate space (UDF logical volume space) >>for >>>> it. >>>> >>>> Additionally, only create a logical partition for UDF logical >>volumes >>>> that are currently supported by EDK2 UDF file system implementation. >>>For >>>> instance, an UDF volume with a single LVD and a single Physical >>(Type >>>1) >>>> Partition will be supported. >>>> >>>> Cc: Eric Dong <eric.d...@intel.com> >>>> Cc: Ruiyu Ni <ruiyu...@intel.com> >>>> Cc: Star Zeng <star.z...@intel.com> >>>> Cc: Laszlo Ersek <ler...@redhat.com> >>>> Reported-by: Ruiyu Ni <ruiyu...@intel.com> >>>> Contributed-under: TianoCore Contribution Agreement 1.1 >>>> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >>>> --- >>>> MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 >>>++-- >>>> MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- >>>> MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 >>>> >>>> MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - >>>> MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 >>>++--- >>>> 5 files changed, 606 insertions(+), 565 deletions(-) >>>> >>>> diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>>> b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>>> index 609f56cef6..572ba7a81a 100644 >>>> --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>>> +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>>> @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( >>>>OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint >>>>) >>>> { >>>> - EFI_STATUS Status; >>>> - UINT32 BlockSize; >>>> - EFI_LBA EndLBA; >>>> - EFI_LBA Descr
Re: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
On September 21, 2017 10:47:07 AM GMT-03:00, "Zeng, Star" <star.z...@intel.com> wrote: >Does it have functional impact? Nope. When Partition driver walks the partition detect routine table, it executes each routine and then checks for EFI_NO_MEDIA and EFI_MEDIA_CHANGED only. So, the child handle is installed and the EFI_NOT_FOUND is a no-op in that case. Thanks! Paulo > >Thanks, >Star >-----Original Message- >From: Paulo Alcantara [mailto:pca...@zytor.com] >Sent: Thursday, September 21, 2017 9:29 PM >To: Wu, Hao A <hao.a...@intel.com>; edk2-devel@lists.01.org >Cc: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com>; >Dong, Eric <eric.d...@intel.com>; Zeng, Star <star.z...@intel.com> >Subject: RE: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >creation of UDF logical partition > > > >On September 21, 2017 9:44:10 AM GMT-03:00, "Wu, Hao A" ><hao.a...@intel.com> wrote: >>One small comment, within function PartitionInstallUdfChildHandles(): >> >> ... >> // >> // Install partition child handle for UDF file system >> // >> Status = PartitionInstallChildHandle ( >>... >>); >>if (!EFI_ERROR (Status)) { <- Is this a typo? "if (EFI_ERROR >>(Status)) {" >>Status = EFI_NOT_FOUND; >> } > >Yes, it is. Good catch! Could you please fix that for me by removing >the if condition? Otherwise I can send a v4 later with that. > >Thanks! >Paulo > >> >> >>Best Regards, >>Hao Wu >> >> >>> -Original Message- >>> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf >>Of Paulo >>> Alcantara >>> Sent: Thursday, September 21, 2017 2:16 AM >>> To: edk2-devel@lists.01.org >>> Cc: Ni, Ruiyu; Laszlo Ersek; Dong, Eric; Zeng, Star >>> Subject: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >>creation of >>> UDF logical partition >>> >>> Do not reserve entire block device size for an UDF file system - >>> instead, reserve the appropriate space (UDF logical volume space) >for >>> it. >>> >>> Additionally, only create a logical partition for UDF logical >volumes >>> that are currently supported by EDK2 UDF file system implementation. >>For >>> instance, an UDF volume with a single LVD and a single Physical >(Type >>1) >>> Partition will be supported. >>> >>> Cc: Eric Dong <eric.d...@intel.com> >>> Cc: Ruiyu Ni <ruiyu...@intel.com> >>> Cc: Star Zeng <star.z...@intel.com> >>> Cc: Laszlo Ersek <ler...@redhat.com> >>> Reported-by: Ruiyu Ni <ruiyu...@intel.com> >>> Contributed-under: TianoCore Contribution Agreement 1.1 >>> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >>> --- >>> MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 >>++-- >>> MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- >>> MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 >>> >>> MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - >>> MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 >>++--- >>> 5 files changed, 606 insertions(+), 565 deletions(-) >>> >>> diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>> b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>> index 609f56cef6..572ba7a81a 100644 >>> --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>> +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >>> @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( >>>OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint >>>) >>> { >>> - EFI_STATUS Status; >>> - UINT32 BlockSize; >>> - EFI_LBA EndLBA; >>> - EFI_LBA DescriptorLBAs[4]; >>> - UINTN Index; >>> + EFI_STATUS Status; >>> + UINT32 BlockSize; >>> + EFI_LBA EndLBA; >>> + EFI_LBA DescriptorLBAs[4]; >>> + UINTN Index; >>> + UDF_DESCRIPTOR_TAG *DescriptorTag; >>> >>>BlockSize = BlockIo->Media->BlockSize; >>>EndLBA = BlockIo->Media->LastBlock; @@ -88,10 +89,13 @@ >>> FindAnchorVolumeDescriptorPointer ( >>> if (EFI_ERROR (Status)) { >>>return Status; >>> } >>> + >>>
Re: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
On September 21, 2017 9:44:10 AM GMT-03:00, "Wu, Hao A" <hao.a...@intel.com> wrote: >One small comment, within function PartitionInstallUdfChildHandles(): > > ... > // > // Install partition child handle for UDF file system > // > Status = PartitionInstallChildHandle ( >... >); >if (!EFI_ERROR (Status)) { <- Is this a typo? "if (EFI_ERROR >(Status)) {" >Status = EFI_NOT_FOUND; > } Yes, it is. Good catch! Could you please fix that for me by removing the if condition? Otherwise I can send a v4 later with that. Thanks! Paulo > > >Best Regards, >Hao Wu > > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf >Of Paulo >> Alcantara >> Sent: Thursday, September 21, 2017 2:16 AM >> To: edk2-devel@lists.01.org >> Cc: Ni, Ruiyu; Laszlo Ersek; Dong, Eric; Zeng, Star >> Subject: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >creation of >> UDF logical partition >> >> Do not reserve entire block device size for an UDF file system - >> instead, reserve the appropriate space (UDF logical volume space) for >> it. >> >> Additionally, only create a logical partition for UDF logical volumes >> that are currently supported by EDK2 UDF file system implementation. >For >> instance, an UDF volume with a single LVD and a single Physical (Type >1) >> Partition will be supported. >> >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Ruiyu Ni <ruiyu...@intel.com> >> Cc: Star Zeng <star.z...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Reported-by: Ruiyu Ni <ruiyu...@intel.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >> --- >> MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 >++-- >> MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- >> MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 >> >> MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - >> MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 >++--- >> 5 files changed, 606 insertions(+), 565 deletions(-) >> >> diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> index 609f56cef6..572ba7a81a 100644 >> --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( >>OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint >>) >> { >> - EFI_STATUS Status; >> - UINT32 BlockSize; >> - EFI_LBA EndLBA; >> - EFI_LBA DescriptorLBAs[4]; >> - UINTN Index; >> + EFI_STATUS Status; >> + UINT32 BlockSize; >> + EFI_LBA EndLBA; >> + EFI_LBA DescriptorLBAs[4]; >> + UINTN Index; >> + UDF_DESCRIPTOR_TAG *DescriptorTag; >> >>BlockSize = BlockIo->Media->BlockSize; >>EndLBA = BlockIo->Media->LastBlock; >> @@ -88,10 +89,13 @@ FindAnchorVolumeDescriptorPointer ( >> if (EFI_ERROR (Status)) { >>return Status; >> } >> + >> +DescriptorTag = >DescriptorTag; >> + >> // >> // Check if read LBA has a valid AVDP descriptor. >> // >> -if (IS_AVDP (AnchorPoint)) { >> +if (DescriptorTag->TagIdentifier == >UdfAnchorVolumeDescriptorPointer) { >>return EFI_SUCCESS; >> } >>} >> @@ -102,23 +106,18 @@ FindAnchorVolumeDescriptorPointer ( >> } >> >> /** >> - Check if block device supports a valid UDF file system as >specified by OSTA >> - Universal Disk Format Specification 2.60. >> + Find UDF volume identifiers in a Volume Recognition Sequence. >> >> - @param[in] BlockIo BlockIo interface. >> - @param[in] DiskIo DiskIo interface. >> + @param[in] BlockIo BlockIo interface. >> + @param[in] DiskIo DiskIo interface. >> >> - @retval EFI_SUCCESS UDF file system found. >> - @retval EFI_UNSUPPORTED UDF file system not found. >> - @retval EFI_NO_MEDIA The device has no media. >> - @retval EFI_DEVICE_ERROR The device reported an error. >> - @retval EFI_VOLUME_CORRUPTED The file system structures are >corrupted. >> - @retval EFI_OUT_OF_RESOURCES T
Re: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
On September 21, 2017 5:49:19 AM GMT-03:00, "Zeng, Star" <star.z...@intel.com> wrote: >VS2015 Build-tested-by: Star Zeng <star.z...@intel.com> > >I have a minor comment to this patch title, how about to use >"MdeModulePkg/UDF: Fix creation of UDF logical partition" as this patch >is touching both PartitionDxe and UdfDxe? Otherwise, you'd better to >split this patch to two, one for PartitionDxe and one for UdfDxe. > >Since the patch could fix the issue we found, and if you agree my minor >comment above, Reviewed-by: Star Zeng <star.z...@intel.com> Thank you all for the tests! Star, I agree with you. Could you please fix the title for me? Also, please add Laszlo's Build-tested-by in the series. Thanks! Paulo > > >Thanks, >Star >-Original Message- >From: Wu, Hao A >Sent: Thursday, September 21, 2017 4:09 PM >To: Paulo Alcantara <pca...@zytor.com>; edk2-devel@lists.01.org >Cc: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com>; >Dong, Eric <eric.d...@intel.com>; Zeng, Star <star.z...@intel.com> >Subject: RE: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >creation of UDF logical partition > >I did a simple test on a Windows8.1 installation DVD, and here's the >result >of a map command under shell: > >Before the patch: >Mapping table > FS0: Alias(s):CD0f65535a1:;BLK2: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/CDROM(0x1) > BLK0: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0) > BLK1: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/CDROM(0x0) > FS1: Alias(s):CD0f65535ab:;BLK5: >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A)/CDROM(0x1) > BLK3: Alias(s): >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A) > BLK4: Alias(s): >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A)/CDROM(0x0) > >After the patch: >Mapping table > FS0: Alias(s):CD0f65535a1:;BLK2: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/CDROM(0x1) > BLK0: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0) > BLK1: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/CDROM(0x0) > BLK3: Alias(s): >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x5,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A) > > >Since the additional file system is gone: >Tested-by: Hao Wu <hao.a...@intel.com> > > >Best Regards, >Hao Wu > >> -Original Message- >> From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf >Of Paulo >> Alcantara >> Sent: Thursday, September 21, 2017 2:16 AM >> To: edk2-devel@lists.01.org >> Cc: Ni, Ruiyu; Laszlo Ersek; Dong, Eric; Zeng, Star >> Subject: [edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix >creation of >> UDF logical partition >> >> Do not reserve entire block device size for an UDF file system - >> instead, reserve the appropriate space (UDF logical volume space) for >> it. >> >> Additionally, only create a logical partition for UDF logical volumes >> that are currently supported by EDK2 UDF file system implementation. >For >> instance, an UDF volume with a single LVD and a single Physical (Type >1) >> Partition will be supported. >> >> Cc: Eric Dong <eric.d...@intel.com> >> Cc: Ruiyu Ni <ruiyu...@intel.com> >> Cc: Star Zeng <star.z...@intel.com> >> Cc: Laszlo Ersek <ler...@redhat.com> >> Reported-by: Ruiyu Ni <ruiyu...@intel.com> >> Contributed-under: TianoCore Contribution Agreement 1.1 >> Signed-off-by: Paulo Alcantara <pca...@zytor.com> >> --- >> MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 >++-- >> MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- >> MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 >> >> MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - >> MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 >++--- >> 5 files changed, 606 insertions(+), 565 deletions(-) >> >> diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> index 609f56cef6..572ba7a81a 100644 >> --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c >> @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( >>OUT UDF_ANCHOR_VOLUME_DESCRIPT
Re: [edk2] [PATCH v3 0/2] UDF partition driver fix
On September 20, 2017 4:25:10 PM GMT-03:00, Laszlo Ersek <ler...@redhat.com> wrote: >On 09/20/17 20:16, Paulo Alcantara wrote: > >> Please, test building these changes in toolchains other than GCC and >> make sure they don't break the world :-) > >> Repo: https://github.com/pcacjr/edk2.git >> Branch: udf-partition-fix-v3 > >I build-tested your branch with OVMF (both IA32 and X64), using: > >- gcc-4.8.5, GCC48, DEBUG >- clang-3.8.1, CLANG38, NOOPT >- gcc-7.1.1, GCC5, DEBUG > >and also cross-built your branch as part of ArmVirtQemu (both ARM and >AARCH64), using: > >- gcc-6.1.1, GCC5, DEBUG > >If it matters, you can add: > >Build-tested-by: Laszlo Ersek <ler...@redhat.com> Of course it does! :-) Thank you very much. You might be wondering why I didn't build-test it with MSVC - well, my wife's laptop got no Visual Studio installed, bul only the necessary 'format' command for formatting my USB stick with UDF :-) Thanks! Paulo -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH v3 1/2] MdePkg: Add UDF volume structure definitions
This patch adds a few more UDF volume structures in order to detect an UDF file system which is supported by current EDK2 UDF file system implementation in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 ++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..002e87e150 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -24,11 +24,28 @@ #define UDF_LOGICAL_SECTOR_SIZE ((UINT64)(1ULL << UDF_LOGICAL_SECTOR_SHIFT)) #define UDF_VRS_START_OFFSET ((UINT64)(16ULL << UDF_LOGICAL_SECTOR_SHIFT)) -#define _GET_TAG_ID(_Pointer) \ - (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +typedef enum { + UdfPrimaryVolumeDescriptor = 1, + UdfAnchorVolumeDescriptorPointer = 2, + UdfVolumeDescriptorPointer = 3, + UdfImplemenationUseVolumeDescriptor = 4, + UdfPartitionDescriptor = 5, + UdfLogicalVolumeDescriptor = 6, + UdfUnallocatedSpaceDescriptor = 7, + UdfTerminatingDescriptor = 8, + UdfLogicalVolumeIntegrityDescriptor = 9, + UdfFileSetDescriptor = 256, + UdfFileIdentifierDescriptor = 257, + UdfAllocationExtentDescriptor = 258, + UdfFileEntry = 261, + UdfExtendedFileEntry = 266, +} UDF_VOLUME_DESCRIPTOR_ID; -#define IS_AVDP(_Pointer) \ - ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define UDF_TAG_ID(_Tag) \ + (UDF_VOLUME_DESCRIPTOR_ID)((_Tag)->TagIdentifier) + +#define UDF_LVD_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix #pragma pack(1) @@ -49,12 +66,50 @@ typedef struct { } UDF_EXTENT_AD; typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + UINT8 IdentifierSuffix[8]; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { UDF_DESCRIPTOR_TAG DescriptorTag; UDF_EXTENT_AD MainVolumeDescriptorSequenceExtent; UDF_EXTENT_AD ReserveVolumeDescriptorSequenceExtent; UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + #pragma pack() #endif -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH v3 2/2] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
Do not reserve entire block device size for an UDF file system - instead, reserve the appropriate space (UDF logical volume space) for it. Additionally, only create a logical partition for UDF logical volumes that are currently supported by EDK2 UDF file system implementation. For instance, an UDF volume with a single LVD and a single Physical (Type 1) Partition will be supported. Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Reported-by: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 ++-- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 ++--- 5 files changed, 606 insertions(+), 565 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 609f56cef6..572ba7a81a 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -64,11 +64,12 @@ FindAnchorVolumeDescriptorPointer ( OUT UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint ) { - EFI_STATUS Status; - UINT32 BlockSize; - EFI_LBA EndLBA; - EFI_LBA DescriptorLBAs[4]; - UINTN Index; + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBA EndLBA; + EFI_LBA DescriptorLBAs[4]; + UINTN Index; + UDF_DESCRIPTOR_TAG *DescriptorTag; BlockSize = BlockIo->Media->BlockSize; EndLBA = BlockIo->Media->LastBlock; @@ -88,10 +89,13 @@ FindAnchorVolumeDescriptorPointer ( if (EFI_ERROR (Status)) { return Status; } + +DescriptorTag = >DescriptorTag; + // // Check if read LBA has a valid AVDP descriptor. // -if (IS_AVDP (AnchorPoint)) { +if (DescriptorTag->TagIdentifier == UdfAnchorVolumeDescriptorPointer) { return EFI_SUCCESS; } } @@ -102,23 +106,18 @@ FindAnchorVolumeDescriptorPointer ( } /** - Check if block device supports a valid UDF file system as specified by OSTA - Universal Disk Format Specification 2.60. + Find UDF volume identifiers in a Volume Recognition Sequence. - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. + @param[in] BlockIo BlockIo interface. + @param[in] DiskIo DiskIo interface. - @retval EFI_SUCCESS UDF file system found. - @retval EFI_UNSUPPORTED UDF file system not found. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of - resources. + @retval EFI_SUCCESS UDF volume identifiers were found. + @retval EFI_NOT_FOUND UDF volume identifiers were not found. + @retval other Failed to perform disk I/O. **/ EFI_STATUS -SupportUdfFileSystem ( +FindUdfVolumeIdentifiers ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo ) @@ -128,7 +127,6 @@ SupportUdfFileSystem ( UINT64EndDiskOffset; CDROM_VOLUME_DESCRIPTOR VolDescriptor; CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor; - UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; ZeroMem ((VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)); @@ -167,7 +165,7 @@ SupportUdfFileSystem ( (CompareMem ((VOID *), (VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)) == 0)) { - return EFI_UNSUPPORTED; + return EFI_NOT_FOUND; } } @@ -176,7 +174,7 @@ SupportUdfFileSystem ( // Offset += UDF_LOGICAL_SECTOR_SIZE; if (Offset >= EndDiskOffset) { -return EFI_UNSUPPORTED; +return EFI_NOT_FOUND; } Status = DiskIo->ReadDisk ( @@ -196,7 +194,7 @@ SupportUdfFileSystem ( (CompareMem ((VOID *)VolDescriptor.Unknown.Id, (VOID *)UDF_NSR3_IDENTIFIER, sizeof (VolDescriptor.Unknown.Id)) != 0)) { -return EFI_UNSUPPORTED; +return EFI_NOT_FOUND; } // @@ -204,7 +202,7 @@ SupportUdfFileSystem ( // Offset += UDF_LOGICAL_SECTOR_SIZE; if (Offset >= EndDiskOffset) { -return EFI_UNSUPPORTED; +return EFI_NOT_FOUND; } Status = DiskIo->ReadDisk ( @@ -221,15 +219,291 @@ SupportUdfFileSystem ( if (CompareMem ((VOID *)VolDescriptor.Unknown.Id,
[edk2] [PATCH v3 0/2] UDF partition driver fix
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707 Hi, This patchset fixes a bug in Partition driver that created UDF logical partitions by using entire block device space and thus polluting protocol database with broken handles. v1->v2: - Followed Laszlo's suggestions to submit a proper patchset. Thanks! - As I'm still waiting for Ruiyu and Star to test this fix, I took advantage of it and did some code cleanups :-) v2->v3: - Followed Ruiyu's suggestions to improve code and add additional checks for ensuring a valid UDF file system and supported by current EDK2 UDF file system implementation. Also run Ecc.py to make sure the files I touched did not break EDK2 C Coding Style, as well as PatchCheck.py for mal-formed patches. I've had a chance to test these changes with my 32GiB USB stick and formatted it on Windows 10 with `format` command. The UDF revisions I tested (by specifying it with "/R:revision") were 1.02, 1.50, 2.00, 2.01 (default) and 2.50. They all worked except the 2.50 revision which adds a Type 2 (Metadata) Partition and it's not supported by current EDK2 UDF implementation -- which handles only Type 1 (Physical) Partitions. The UDF 2.60 revision I tested with the usual `sudo mkudffs -b 512 --media-type=hd /dev/sdX` command in Linux. Remember, the *officially* supported revision is 2.60, however all revisions use the same volume structures as defined by ECMA 167 specification, and they usually differ from each other by means of new optional features, so that's why all those revisions worked with this implementation. Well, at least this what I understood when looking at the specifications. Please correct me if I'm wrong. Please, test building these changes in toolchains other than GCC and make sure they don't break the world :-) Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix-v3 Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Jiewen Yao <jiewen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Ruiyu Ni <ruiyu...@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (2): MdePkg: Add UDF volume structure definitions MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 363 ++-- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 16 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 627 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 158 ++--- MdePkg/Include/IndustryStandard/Udf.h | 63 +- 6 files changed, 665 insertions(+), 569 deletions(-) -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v2 0/3] UDF partition driver fix
Hi Ruiyu, On 9/18/2017 1:52 AM, Ni, Ruiyu wrote: Paulo, Could you please paste a "map -r" output on a CDROM which contains Eltorito volume? I want to confirm that the result is expected. With UdfDxe driver disabled in OVMF: >Mapping table > FS0: Alias(s):CD0c65535a1:;BLK2: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/CDROM(0x1) > BLK0: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0) > BLK1: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/CDROM(0x0) > BLK3: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A) With UdfDxe driver enabled in OVMF: > Mapping table > FS0: Alias(s):CD0c65535a1:;BLK2: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/CDROM(0x1) > FS1: Alias(s):F0c65535a:;BLK3: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A) > BLK0: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0) > BLK1: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x2,0x,0x0)/CDROM(0x0) Thanks! Paulo Thanks/Ray -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Sunday, September 17, 2017 9:13 PM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Kinney, Michael D <michael.d.kin...@intel.com>; Gao, Liming <liming@intel.com>; Laszlo Ersek <ler...@redhat.com>; Ni, Ruiyu <ruiyu...@intel.com>; Zeng, Star <star.z...@intel.com>; Yao, Jiewen <jiewen@intel.com> Subject: [PATCH v2 0/3] UDF partition driver fix REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707 Hi, This patchset fixes a bug in Partition driver that UDF partitions occupied the entire disk space instead of using LVD space only. BTW, I've only tested it under OVMF and built it with GCC only. That would be appreciable if someone could build with other toolchains and see if this doesn't break. I used a Windows 10 ISO image with UdfDxe disabled and enabled. The `map -r` output seemed OK. No breakage when booting an OS off an ElTorito partition from an UDF bridge disk. v1->v2: - Followed Laszlo's suggestions to submit a proper patchset. Thanks! - As I'm still waiting for Ruiyu and Star to test this fix, I took advantage of it and did some code cleanups :-) Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix-v2 Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Jiewen Yao <jiewen....@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Ruiyu Ni <ruiyu...@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (3): MdePkg: Add UDF volume structure definitions MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 323 +++- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 515 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- MdePkg/Include/IndustryStandard/Udf.h | 63 +++ 6 files changed, 566 insertions(+), 443 deletions(-) -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH v2 3/3] MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes
On 9/17/2017 10:00 PM, Ni, Ruiyu wrote: Paulo, With the change in partition driver, I suppose UdfDxe driver only needs to take care of area covered by the partition descriptor. But why StartMainVolumeDescriptorSequence() still reads LVD, TD, and PD? We still need the LVD again for a few reasons: 1. GetVolumeSize() needs to read LVID (Logical Volume Integrity Descriptor), which is located in LVD, in order to calculate free and used volume space. 2. To find FSD (File Set Descriptor), where the root directory is located. 3. To know which Partition Descriptor to use based on partition number from LVD->PartitionMaps field. I know UDF 2.60 spec says that there should be only one Partition Descriptor that covers the entire space of a single LVD, but it's good to make sure we're reading it correctly. TD descriptor is used to know when stopping the Volume Descriptor Sequence and then we don't need to read all ExtentAd->ExtentLength blocks unnecessarily. Thanks, Paulo I thought the UdfDxe driver's logic can be simplified a lot. There should be no duplicated logic in Partition driver and udf driver. Can you explain more? Thanks/Ray -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Sunday, September 17, 2017 9:13 PM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Dong, Eric <eric.d...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>; Zeng, Star <star.z...@intel.com>; Laszlo Ersek <ler...@redhat.com> Subject: [PATCH v2 3/3] MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes This patch reworks the driver to support Partition driver changes. Cc: Eric Dong <eric.d...@intel.com> Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 515 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- 4 files changed, 204 insertions(+), 419 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c index 01361141bb..f2c62967e8 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c @@ -100,6 +100,7 @@ UdfOpenVolume ( >Volume, >Root ); + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { goto Error_Find_Root_Dir; } @@ -131,7 +132,6 @@ Error_Alloc_Priv_File_Data: CleanupFileInformation (>Root); Error_Find_Root_Dir: - CleanupVolumeInformation (>Volume); Error_Read_Udf_Volume: Error_Invalid_Params: @@ -528,7 +528,6 @@ UdfClose ( EFI_TPL OldTpl; EFI_STATUS Status; PRIVATE_UDF_FILE_DATA *PrivFileData; - PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); @@ -541,8 +540,6 @@ UdfClose ( PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); - PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData- SimpleFs); - if (!PrivFileData->IsRootDirectory) { CleanupFileInformation (>File); @@ -551,10 +548,6 @@ UdfClose ( } } - if (--PrivFsData->OpenFiles == 0) { -CleanupVolumeInformation (>Volume); - } - FreePool ((VOID *)PrivFileData); Exit: @@ -787,7 +780,7 @@ UdfGetInfo ( } else if (CompareGuid (InformationType, )) { String = VolumeLabel; -FileSetDesc = PrivFsData->Volume.FileSetDescs[0]; +FileSetDesc = >Volume.FileSetDesc; OstaCompressed = >LogicalVolumeIdentifier[0]; @@ -846,7 +839,7 @@ UdfGetInfo ( FileSystemInfo->Size= FileSystemInfoLength; FileSystemInfo->ReadOnly= TRUE; FileSystemInfo->BlockSize = - LV_BLOCK_SIZE (>Volume, UDF_DEFAULT_LV_NUM); + PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize; FileSystemInfo->VolumeSize = VolumeSize; FileSystemInfo->FreeSpace = FreeSpaceSize; diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c index 4609580b30..63b643e60a 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c @@ -60,154 +60,111 @@ FindAnchorVolumeDescriptorPointer ( EFI_STATUS StartMainVolumeDescriptorSequence ( - IN EFI_BLOCK_IO_PROTOCOL *BlockIo, - IN EFI_DISK_IO_PROTOCOL *DiskIo, - IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, - OUT UDF_VOLUME_INFO *Volume + IN EFI_BLOCK_IO
Re: [edk2] [PATCH v2 2/3] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
Hi, On 9/17/2017 9:54 PM, Ni, Ruiyu wrote: Paulo, Several comments: 1. Can below logic be removed in PartitionDxe/Udf.c? while (!IsDevicePathEnd (DevicePathNode)) { // // Do not allow checking for UDF file systems in CDROM "El Torito" // partitions, and skip duplicate installation of UDF file system child // nodes. // if (DevicePathType (DevicePathNode) == MEDIA_DEVICE_PATH) { if (DevicePathSubType (DevicePathNode) == MEDIA_CDROM_DP) { return EFI_NOT_FOUND; } if (DevicePathSubType (DevicePathNode) == MEDIA_VENDOR_DP) { VendorDefinedGuid = (EFI_GUID *)((UINTN)DevicePathNode + OFFSET_OF (VENDOR_DEVICE_PATH, Guid)); if (CompareGuid (VendorDefinedGuid, )) { return EFI_NOT_FOUND; } } } // // Try next device path node // DevicePathNode = NextDevicePathNode (DevicePathNode); } I think it's no longer necessary, so I'll remove it. 2. Can you add function header comments for the newly added functions? Sure. 3. Change the consuming code of IS_UDF_XXX macro after patch #1 is changed. ACK. 4. Perhaps to add more checks for these numbers read from the UDF CDROM. As Jiewen mentioned in another mail, secure code needs to validate all external inputs. We shouldn't assume the UDF CDROM is a well-formatted CDROM. A hacker may create a UDF CDROM to hack the system by using mechanism like buffer overflow, integer overflow, etc. OK, when we start the Main Volume Descriptor Sequence (MVDS), we rely on "ExtentAd->ExtentLocation" to know the LBA where to start the sequence, and on "ExtentAd->ExtentLength" to know many LBAs the sequence has. We only care about LVD, PD and TD descriptors. We currently check whether a TD descriptor exists, or the search exceed ExtentAd->ExtentLength blocks to determine when stopping the sequence. That doesn't seem to be safe enough, but here are some thoughts: a. "ExtentAd->ExtentLength" may point to a bad value. If it's greater than or equal to BlockIo->Media->LastBlock, and there is no TD descriptor, we'll have to walk the entire disk and there will too much I/O overhead and then impacting bootup. Obviously, when it's greater than LastBlock, DiksIo->ReadDisk() should not allow to read a non-existent LBA and then return EFI_INVALID_PARAMETER, as per UEFI spec. b. "ExtentAd->ExtentLocation" might point to a invalid LBA, although DiskIo->ReadDisk() would not allow it. So, it's time to look at UDF 2.60 spec again: > Volume Descriptor Sequence Extent > > Both the main and reserve volume descriptor sequence extents > shall each have a minimum length of 16 logical sectors. The VDS > Extent may be terminated by the extent length. It doesn't tell us either a limit of logical blocks, or a maximum number. Next: > 6.9.2.3 Step 3. Volume Descriptor Sequence > Read logical sectors: > MVDS_Location through MVDS_Location + (MVDS_Length - 1) / SectorSize > ... MVDS_Length == ExtentAd->ExtentLength, so still insufficient. Next: > The data located in bytes 0-3 and 5 of the Anchor Volume Descriptor Pointer may be > used for format verification if desired. Verifying the Tag Checksum in byte 4 and > Descriptor CRC in bytes 8-11 are good additional verifications to perform. > MVDS_Location and MVDS_Length are read from this structure. Seems like a great check prior to reading ExtentAd->ExtentLocation and ExtentAd->ExtentLength contents. Would that be sufficient to you? I haven't found a way to limit the number of blocks a Volume Descriptor Sequence might have. Thanks, Paulo Thanks/Ray -Original Message----- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Sunday, September 17, 2017 9:13 PM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Dong, Eric <eric.d...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>; Zeng, Star <star.z...@intel.com>; Laszlo Ersek <ler...@redhat.com> Subject: [PATCH v2 2/3] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition Do not use entire block device size for the UDF logical partition, instead reserve the appropriate space (LVD space) for it. Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Reported-by: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 323 ++-- 1 file changed, 299 insertions(+), 24 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 7856b5dfc1..3e84882922 100644 --- a/MdeModulePkg/Universal/D
Re: [edk2] [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions
Hi, On 9/17/2017 9:42 PM, Ni, Ruiyu wrote: Continue reading the patch #2, I think we can change IS_PD to: #define IS_UDF_PD(Tag) ((Tag)->TagIdentifier == 5) Using the above way, we can avoid caller to supply an invalid buffer. Good point. I'll fix it. Thanks! Paulo Thanks/Ray -Original Message- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Ni, Ruiyu Sent: Monday, September 18, 2017 8:29 AM To: Paulo Alcantara <pca...@zytor.com>; edk2-devel@lists.01.org Cc: Kinney, Michael D <michael.d.kin...@intel.com>; Laszlo Ersek <ler...@redhat.com>; Gao, Liming <liming@intel.com> Subject: Re: [edk2] [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) #define IS_PD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) #define IS_LVD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) #define IS_TD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) Paulo, If you take a look at Pci22.h in the same directory, all macros are started as "IS_PCI_". How about changing the above IS_xxx to IS_UDF_xxx? Shall we change AVDP to AVD, following the same naming style as PD, LVD and TD? How about changing _Pointer to _Tag or DescriptorTag? Thanks/Ray -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Sunday, September 17, 2017 9:13 PM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Kinney, Michael D <michael.d.kin...@intel.com>; Gao, Liming <liming@intel.com>; Laszlo Ersek <ler...@redhat.com>; Ni, Ruiyu <ruiyu...@intel.com> Subject: [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions This patch adds a fewe more UDF structures in order to detect Logical Volume and Partition descriptors during Main Volume Descriptor Sequence in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 1 file changed, 63 insertions(+) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..6cc42f8543 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -27,9 +27,19 @@ #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +#define IS_PD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) #define IS_LVD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) #define IS_TD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) + #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define LV_UDF_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix + #pragma pack(1) typedef struct { @@ -55,6 +65,59 @@ typedef struct { UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + UINT8 IdentifierSuffix[8]; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UINT16 PartitionFlags; + UINT16 PartitionNumber; + UDF_ENTITY_ID PartitionContents; + UINT8 PartitionContentsU
Re: [edk2] [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions
Hi Ruiyu, On 9/17/2017 9:28 PM, Ni, Ruiyu wrote: #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) #define IS_PD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) #define IS_LVD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) #define IS_TD(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) Paulo, If you take a look at Pci22.h in the same directory, all macros are started as "IS_PCI_". How about changing the above IS_xxx to IS_UDF_xxx? Looks good to me. I'll change them. Shall we change AVDP to AVD, following the same naming style as PD, LVD and TD? There is no "Anchor Volume Descriptor" but "Anchor Volume Descriptor Pointer", so we still need to keep 'P'. How about changing _Pointer to _Tag or DescriptorTag? I will change it to _Tag. _Pointer is really a bad name. Thanks! :-) Paulo Thanks/Ray -Original Message- From: Paulo Alcantara [mailto:pca...@zytor.com] Sent: Sunday, September 17, 2017 9:13 PM To: edk2-devel@lists.01.org Cc: Paulo Alcantara <pca...@zytor.com>; Kinney, Michael D <michael.d.kin...@intel.com>; Gao, Liming <liming@intel.com>; Laszlo Ersek <ler...@redhat.com>; Ni, Ruiyu <ruiyu...@intel.com> Subject: [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions This patch adds a fewe more UDF structures in order to detect Logical Volume and Partition descriptors during Main Volume Descriptor Sequence in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 1 file changed, 63 insertions(+) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..6cc42f8543 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -27,9 +27,19 @@ #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +#define IS_PD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) #define IS_LVD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) #define IS_TD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) + #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define LV_UDF_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix + #pragma pack(1) typedef struct { @@ -55,6 +65,59 @@ typedef struct { UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + UINT8 IdentifierSuffix[8]; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UINT16 PartitionFlags; + UINT16 PartitionNumber; + UDF_ENTITY_ID PartitionContents; + UINT8 PartitionContentsUse[128]; + UINT32 AccessType; + UINT32 PartitionStartingLocation; + UINT32 PartitionLength; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UINT8 Reserved[156]; +} UDF_PARTITION_DESCRIPTOR; + #pragma pack() #endif -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 0/3] UDF partition driver fix
and check the remaining unsupported features. I ask this, because we want to understand how we declare the support level of this UEFI UDF driver. If we just say we support UDF, then naive people may believe we support everything. J Yes :-) 3)Which compatibility test has been done? I am sorry that I cannot find the first version patch. I fund you mentioned Win10 ISO is tried in V2. Any more? We would like to know how many existing OS installation CDROM (or any other CDROM) has been tried. Such as Linux (RedHat, Ubuntu, Suse, etc), or Windows (Win7, Win8, Win10)? Currently, I'm only using a Windows 10 Enterprise ISO image. But I also tested it with Windows 8 ISO images as well (in 3 years ago :-) ) Like I said, the Fedora ISO image I have didn't serve because it has no UDF file system. Wondering if any other Linux ISO image contains an UDF file system. The more detail, the better. May a list. 4)The last but not least important, which negative test (security test) has been done? None. Have you run some fuzzing test? No. Have you tried a mal-format UDF disc? For example, with bad offset or length? No. Have you test the integer overflow / buffer over flow handing in the code? No. NOTE: we should not use ASSERT to handle such error. When I review the code, I found below: Status = ReadFileData ( BlockIo, DiskIo, Volume, Parent, PrivFileData->FileSize, >FilePosition, Buffer, ); ASSERT (BufferSizeUint64 <= MAX_UINTN); *BufferSize = (UINTN)BufferSizeUint64; I am not sure if we can use ASSERT (BufferSizeUint64 <= MAX_UINTN); Can a malicious user construct a bad UDF and make BufferSizeUint64 > MAX_UINTN? Does it might happen? Or never happen? Laszlo already answered :-) We documented Appendix B - EDKII code review top 5 in https://github.com/tianocore-docs/Docs/raw/master/White_Papers/A_Tour_Beyond_BIOS_Security_Design_Guide_in_EDK_II.pdf 3 of them are matched in these partition and file system drivers. I quote below: === *If the code consumes input from an untrusted source or region,* Ensure that the input is rigorously and adequately validated. *Verify buffer overflow is handled. Avoid integer overflow.* Try to use subtraction instead of addition and division instead of multiplication. *Verify that ASSERT is used properly.* ASSERT is used to catch conditions that should /never /happen. If something /might /happen, use error handling instead. We can use both ASSERT and error handling to facilitate debugging – ASSERT allows for earlier detection and isolation of several classes of issues. [McConnell] === It is just a reminder. If you are already following that, it will be great. Please let us now. No, I wasn't. But I will make sure to follow that rigorously next time. Very good info. Thanks! I take a glance of UDF 2.6 specification, but I do not have chance to read all content at this moment. If I asked some stupid question , please feel free to correct me. Not that I know of. I'm also not an UDF expert. I do enjoy writing read-only fs drivers in my free time, that is. :-) All in all, we hope to understand the current quality level of the UDF partition support and UDF file system. Sure. You're completely right by asking such questions. If we really want to make proper use of it, the more understanding, testing, documentation, the better. Thank you very much for all the questions and suggestions. Really appreciate it. I hope you guys (+ community) to test this implementation, report bugs, etc. as much as possible. I wish I could work on it full time and give better support for you guys. Unfortunately I can't. But I'll do my best in giving you some support. Thanks! Paulo If you can help to provide the detail, it may help us to evaluate. Thank you Yao Jiewen *From:*edk2-devel [mailto:edk2-devel-boun...@lists.01.org] *On Behalf Of *Laszlo Ersek *Sent:* Sunday, September 17, 2017 6:17 AM *To:* Paulo Alcantara <pca...@zytor.com> *Cc:* Ni, Ruiyu <ruiyu...@intel.com>; Dong, Eric <eric.d...@intel.com>; edk2-devel@lists.01.org; Gao, Liming <liming@intel.com>; Kinney, Michael D <michael.d.kin...@intel.com>; Zeng, Star <star.z...@intel.com> *Subject:* Re: [edk2] [PATCH 0/3] UDF partition driver fix Hi Paulo, On 09/16/17 23:36, Paulo Alcantara wrote: This series fixes an UDF issue with Partition driver as discussed in ML: https://lists.01.org/pipermail/edk2-devel/2017-September/014694.html Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix Paulo Alcantara (3): MdePkg: Add UDF volume structure definitions MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes MdeModulePkg/Univers
[edk2] [PATCH v2 2/3] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
Do not use entire block device size for the UDF logical partition, instead reserve the appropriate space (LVD space) for it. Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Reported-by: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 323 ++-- 1 file changed, 299 insertions(+), 24 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 7856b5dfc1..3e84882922 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -84,24 +84,8 @@ FindAnchorVolumeDescriptorPointer ( return EFI_VOLUME_CORRUPTED; } -/** - Check if block device supports a valid UDF file system as specified by OSTA - Universal Disk Format Specification 2.60. - - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. - - @retval EFI_SUCCESS UDF file system found. - @retval EFI_UNSUPPORTED UDF file system not found. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of - resources. - -**/ EFI_STATUS -SupportUdfFileSystem ( +FindUdfVolumeIdentifiers ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo ) @@ -111,7 +95,6 @@ SupportUdfFileSystem ( UINT64EndDiskOffset; CDROM_VOLUME_DESCRIPTOR VolDescriptor; CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor; - UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; ZeroMem ((VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)); @@ -207,12 +190,302 @@ SupportUdfFileSystem ( return EFI_UNSUPPORTED; } + return EFI_SUCCESS; +} + +EFI_STATUS +GetPartitionNumber ( + IN UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc, + OUT UINT16 *PartitionNum + ) +{ + EFI_STATUS Status; + UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd; + + Status = EFI_SUCCESS; + + switch (LV_UDF_REVISION (LogicalVolDesc)) { + case 0x0102: +// +// UDF 1.20 only supports Type 1 Partition +// +*PartitionNum = *(UINT16 *)((UINTN)>PartitionMaps[4]); +break; + case 0x0150: +// +// Ensure Type 1 Partition map +// +ASSERT (LogicalVolDesc->PartitionMaps[0] == 1 && +LogicalVolDesc->PartitionMaps[1] == 6); +*PartitionNum = *(UINT16 *)((UINTN)>PartitionMaps[4]); +break; + case 0x0260: +LongAd = >LogicalVolumeContentsUse; +*PartitionNum = LongAd->ExtentLocation.PartitionReferenceNumber; +break; + default: +// +// Unhandled UDF revision +// +Status = EFI_VOLUME_CORRUPTED; +break; + } + + return Status; +} + +EFI_STATUS +FindLogicalVolumeLocation ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, + OUT UINT64*MainVdsStartLsn, + OUT UINT64*LogicalVolEndLsn + ) +{ + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBALastBlock; + UDF_EXTENT_AD *ExtentAd; + UINT64 StartingLsn; + UINT64 EndingLsn; + VOID *Buffer; + UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc; + UDF_PARTITION_DESCRIPTOR *PartitionDesc; + UINT64 GuardMainVdsStartLsn; + UINT16 PartitionNum; + + BlockSize = BlockIo->Media->BlockSize; + LastBlock = BlockIo->Media->LastBlock; + ExtentAd = >MainVolumeDescriptorSequenceExtent; + StartingLsn = (UINT64)ExtentAd->ExtentLocation; + EndingLsn = +StartingLsn + DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize); + + LogicalVolDesc= NULL; + PartitionDesc = NULL; + GuardMainVdsStartLsn = StartingLsn; + + // + // Allocate buffer for reading disk blocks + // + Buffer = AllocateZeroPool (BlockSize); + if (Buffer == NULL) { +return EFI_OUT_OF_RESOURCES; + } + + Status = EFI_VOLUME_CORRUPTED; + + // + // As per UDF 2.60 specification: + // + // There shall be exactly one prevailing Logical Volume Descriptor + // recorded per Volume Set. + // + // Start Main Volume Descriptor Sequence and find Logical Volume Descriptor + // + while (StartingLsn <
[edk2] [PATCH v2 0/3] UDF partition driver fix
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=707 Hi, This patchset fixes a bug in Partition driver that UDF partitions occupied the entire disk space instead of using LVD space only. BTW, I've only tested it under OVMF and built it with GCC only. That would be appreciable if someone could build with other toolchains and see if this doesn't break. I used a Windows 10 ISO image with UdfDxe disabled and enabled. The `map -r` output seemed OK. No breakage when booting an OS off an ElTorito partition from an UDF bridge disk. v1->v2: - Followed Laszlo's suggestions to submit a proper patchset. Thanks! - As I'm still waiting for Ruiyu and Star to test this fix, I took advantage of it and did some code cleanups :-) Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix-v2 Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Jiewen Yao <jiewen@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Ruiyu Ni <ruiyu...@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- Paulo Alcantara (3): MdePkg: Add UDF volume structure definitions MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 323 +++- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 515 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- MdePkg/Include/IndustryStandard/Udf.h | 63 +++ 6 files changed, 566 insertions(+), 443 deletions(-) -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH v2 3/3] MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes
This patch reworks the driver to support Partition driver changes. Cc: Eric Dong <eric.d...@intel.com> Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 515 MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- 4 files changed, 204 insertions(+), 419 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c index 01361141bb..f2c62967e8 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c @@ -100,6 +100,7 @@ UdfOpenVolume ( >Volume, >Root ); + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { goto Error_Find_Root_Dir; } @@ -131,7 +132,6 @@ Error_Alloc_Priv_File_Data: CleanupFileInformation (>Root); Error_Find_Root_Dir: - CleanupVolumeInformation (>Volume); Error_Read_Udf_Volume: Error_Invalid_Params: @@ -528,7 +528,6 @@ UdfClose ( EFI_TPL OldTpl; EFI_STATUS Status; PRIVATE_UDF_FILE_DATA *PrivFileData; - PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); @@ -541,8 +540,6 @@ UdfClose ( PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); - PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs); - if (!PrivFileData->IsRootDirectory) { CleanupFileInformation (>File); @@ -551,10 +548,6 @@ UdfClose ( } } - if (--PrivFsData->OpenFiles == 0) { -CleanupVolumeInformation (>Volume); - } - FreePool ((VOID *)PrivFileData); Exit: @@ -787,7 +780,7 @@ UdfGetInfo ( } else if (CompareGuid (InformationType, )) { String = VolumeLabel; -FileSetDesc = PrivFsData->Volume.FileSetDescs[0]; +FileSetDesc = >Volume.FileSetDesc; OstaCompressed = >LogicalVolumeIdentifier[0]; @@ -846,7 +839,7 @@ UdfGetInfo ( FileSystemInfo->Size= FileSystemInfoLength; FileSystemInfo->ReadOnly= TRUE; FileSystemInfo->BlockSize = - LV_BLOCK_SIZE (>Volume, UDF_DEFAULT_LV_NUM); + PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize; FileSystemInfo->VolumeSize = VolumeSize; FileSystemInfo->FreeSpace = FreeSpaceSize; diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c index 4609580b30..63b643e60a 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c @@ -60,154 +60,111 @@ FindAnchorVolumeDescriptorPointer ( EFI_STATUS StartMainVolumeDescriptorSequence ( - IN EFI_BLOCK_IO_PROTOCOL *BlockIo, - IN EFI_DISK_IO_PROTOCOL *DiskIo, - IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, - OUT UDF_VOLUME_INFO *Volume + IN EFI_BLOCK_IO_PROTOCOL*BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT UDF_VOLUME_INFO *Volume ) { - EFI_STATUS Status; - UINT32 BlockSize; - UDF_EXTENT_AD *ExtentAd; - UINT64 StartingLsn; - UINT64 EndingLsn; - VOID *Buffer; - UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc; - UDF_PARTITION_DESCRIPTOR *PartitionDesc; - UINTN Index; - UINT32 LogicalBlockSize; + EFI_STATUS Status; + UINT32 BlockSize; + UINT64 BlockOffset; + VOID*Buffer; + UINT32 LogicalBlockSize; + + BlockSize = BlockIo->Media->BlockSize; // - // We've already found an ADVP on the volume. It contains the extent - // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor - // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and - // Partitions Descriptors and save them in memory, accordingly. - // - // Note also that each descriptor will be aligned on a block size (BlockSize) - // boundary, so we need to read one block at a time. + // Allocate buffer for reading disk blocks // - BlockSize= BlockIo->Media->BlockSize; - ExtentAd = >MainVolumeDescriptorSequenceExtent; - StartingLsn = (UINT64)ExtentAd->ExtentLocation; - EndingLsn= StartingLsn + DivU64x32 ( - (UINT64)ExtentAd->ExtentLength, - BlockSize - ); - - Volum
[edk2] [PATCH v2 1/3] MdePkg: Add UDF volume structure definitions
This patch adds a fewe more UDF structures in order to detect Logical Volume and Partition descriptors during Main Volume Descriptor Sequence in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 1 file changed, 63 insertions(+) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..6cc42f8543 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -27,9 +27,19 @@ #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +#define IS_PD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) +#define IS_LVD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) +#define IS_TD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) + #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define LV_UDF_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix + #pragma pack(1) typedef struct { @@ -55,6 +65,59 @@ typedef struct { UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + UINT8 IdentifierSuffix[8]; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UINT16 PartitionFlags; + UINT16 PartitionNumber; + UDF_ENTITY_ID PartitionContents; + UINT8 PartitionContentsUse[128]; + UINT32 AccessType; + UINT32 PartitionStartingLocation; + UINT32 PartitionLength; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UINT8 Reserved[156]; +} UDF_PARTITION_DESCRIPTOR; + #pragma pack() #endif -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH 0/3] UDF partition driver fix
This series fixes an UDF issue with Partition driver as discussed in ML: https://lists.01.org/pipermail/edk2-devel/2017-September/014694.html Thanks! Paulo Repo: https://github.com/pcacjr/edk2.git Branch: udf-partition-fix Paulo Alcantara (3): MdePkg: Add UDF volume structure definitions MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 307 +++- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- .../Universal/Disk/UdfDxe/FileSystemOperations.c | 525 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- MdePkg/Include/IndustryStandard/Udf.h | 63 +++ 6 files changed, 560 insertions(+), 443 deletions(-) -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH 1/3] MdePkg: Add UDF volume structure definitions
This patch adds a fewe more UDF structures in order to detect Logical Volume and Partition descriptors during Main Volume Descriptor Sequence in Partition driver. Cc: Michael D Kinney <michael.d.kin...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdePkg/Include/IndustryStandard/Udf.h | 63 +++ 1 file changed, 63 insertions(+) diff --git a/MdePkg/Include/IndustryStandard/Udf.h b/MdePkg/Include/IndustryStandard/Udf.h index 0febb4bcda..6cc42f8543 100644 --- a/MdePkg/Include/IndustryStandard/Udf.h +++ b/MdePkg/Include/IndustryStandard/Udf.h @@ -27,9 +27,19 @@ #define _GET_TAG_ID(_Pointer) \ (((UDF_DESCRIPTOR_TAG *)(_Pointer))->TagIdentifier) +#define IS_PD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 5)) +#define IS_LVD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 6)) +#define IS_TD(_Pointer) \ + ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 8)) + #define IS_AVDP(_Pointer) \ ((BOOLEAN)(_GET_TAG_ID (_Pointer) == 2)) +#define LV_UDF_REVISION(_Lv) \ + *(UINT16 *)(UINTN)(_Lv)->DomainIdentifier.IdentifierSuffix + #pragma pack(1) typedef struct { @@ -55,6 +65,59 @@ typedef struct { UINT8 Reserved[480]; } UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER; +typedef struct { + UINT8 CharacterSetType; + UINT8 CharacterSetInfo[63]; +} UDF_CHAR_SPEC; + +typedef struct { + UINT8 Flags; + UINT8 Identifier[23]; + UINT8 IdentifierSuffix[8]; +} UDF_ENTITY_ID; + +typedef struct { + UINT32LogicalBlockNumber; + UINT16PartitionReferenceNumber; +} UDF_LB_ADDR; + +typedef struct { + UINT32 ExtentLength; + UDF_LB_ADDR ExtentLocation; + UINT8ImplementationUse[6]; +} UDF_LONG_ALLOCATION_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UDF_CHAR_SPEC DescriptorCharacterSet; + UINT8 LogicalVolumeIdentifier[128]; + UINT32 LogicalBlockSize; + UDF_ENTITY_ID DomainIdentifier; + UDF_LONG_ALLOCATION_DESCRIPTOR LogicalVolumeContentsUse; + UINT32 MapTableLength; + UINT32 NumberOfPartitionMaps; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UDF_EXTENT_AD IntegritySequenceExtent; + UINT8 PartitionMaps[6]; +} UDF_LOGICAL_VOLUME_DESCRIPTOR; + +typedef struct { + UDF_DESCRIPTOR_TAG DescriptorTag; + UINT32 VolumeDescriptorSequenceNumber; + UINT16 PartitionFlags; + UINT16 PartitionNumber; + UDF_ENTITY_ID PartitionContents; + UINT8 PartitionContentsUse[128]; + UINT32 AccessType; + UINT32 PartitionStartingLocation; + UINT32 PartitionLength; + UDF_ENTITY_ID ImplementationIdentifier; + UINT8 ImplementationUse[128]; + UINT8 Reserved[156]; +} UDF_PARTITION_DESCRIPTOR; + #pragma pack() #endif -- 2.11.0 ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
[edk2] [PATCH 2/3] MdeModulePkg/PartitionDxe: Fix creation of UDF logical partition
Do not use entire block device size for the UDF logical partition, instead reserve the appropriate space (LVD space) for it. Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Reported-by: Ruiyu Ni <ruiyu...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c | 307 +++-- 1 file changed, 283 insertions(+), 24 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c index 7856b5dfc1..b00369ba6d 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c @@ -84,24 +84,8 @@ FindAnchorVolumeDescriptorPointer ( return EFI_VOLUME_CORRUPTED; } -/** - Check if block device supports a valid UDF file system as specified by OSTA - Universal Disk Format Specification 2.60. - - @param[in] BlockIo BlockIo interface. - @param[in] DiskIo DiskIo interface. - - @retval EFI_SUCCESS UDF file system found. - @retval EFI_UNSUPPORTED UDF file system not found. - @retval EFI_NO_MEDIA The device has no media. - @retval EFI_DEVICE_ERROR The device reported an error. - @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. - @retval EFI_OUT_OF_RESOURCES The scan was not successful due to lack of - resources. - -**/ EFI_STATUS -SupportUdfFileSystem ( +FindUdfVolumeIdentifiers ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo ) @@ -111,7 +95,6 @@ SupportUdfFileSystem ( UINT64EndDiskOffset; CDROM_VOLUME_DESCRIPTOR VolDescriptor; CDROM_VOLUME_DESCRIPTOR TerminatingVolDescriptor; - UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER AnchorPoint; ZeroMem ((VOID *), sizeof (CDROM_VOLUME_DESCRIPTOR)); @@ -207,12 +190,286 @@ SupportUdfFileSystem ( return EFI_UNSUPPORTED; } + return EFI_SUCCESS; +} + +EFI_STATUS +GetPartitionNumber ( + IN UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc, + OUT UINT16 *PartitionNum + ) +{ + EFI_STATUS Status; + UDF_LONG_ALLOCATION_DESCRIPTOR *LongAd; + + Status = EFI_SUCCESS; + + switch (LV_UDF_REVISION (LogicalVolDesc)) { + case 0x0102: +// +// UDF 1.20 only supports Type 1 Partition +// +*PartitionNum = *(UINT16 *)((UINTN)>PartitionMaps[4]); +break; + case 0x0150: +// +// Ensure Type 1 Partition map +// +ASSERT (LogicalVolDesc->PartitionMaps[0] == 1 && +LogicalVolDesc->PartitionMaps[1] == 6); +*PartitionNum = *(UINT16 *)((UINTN)>PartitionMaps[4]); +break; + case 0x0260: +LongAd = >LogicalVolumeContentsUse; +*PartitionNum = LongAd->ExtentLocation.PartitionReferenceNumber; +break; + default: +// +// Unhandled UDF revision +// +Status = EFI_VOLUME_CORRUPTED; +break; + } + + return Status; +} + +EFI_STATUS +FindLogicalVolumeLocation ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, + OUT UINT64*MainVdsStartLsn, + OUT UINT64*LogicalVolEndLsn + ) +{ + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBALastBlock; + UDF_EXTENT_AD *ExtentAd; + UINT64 StartingLsn; + UINT64 EndingLsn; + VOID *Buffer; + UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc; + UDF_PARTITION_DESCRIPTOR *PartitionDesc; + UINT64 GuardMainVdsStartLsn; + UINT16 PartitionNum; + + BlockSize = BlockIo->Media->BlockSize; + LastBlock = BlockIo->Media->LastBlock; + ExtentAd = >MainVolumeDescriptorSequenceExtent; + StartingLsn = (UINT64)ExtentAd->ExtentLocation; + EndingLsn = +StartingLsn + DivU64x32 ((UINT64)ExtentAd->ExtentLength, BlockSize); + + LogicalVolDesc= NULL; + PartitionDesc = NULL; + GuardMainVdsStartLsn = StartingLsn; + + // + // Allocate buffer for reading disk blocks + // + Buffer = AllocateZeroPool (BlockSize); + if (Buffer == NULL) { +return EFI_OUT_OF_RESOURCES; + } + + Status = EFI_VOLUME_CORRUPTED; + + // + // As per UDF 2.60 specification: + // + // There shall be exactly one prevailing Logical Volume Descriptor + // recorded per Volume Set. + // + // Start Main Volume Descriptor Sequence and find Logical Volume Descriptor + // + while (StartingLsn <
[edk2] [PATCH 3/3] MdeModulePkg/UdfDxe: Rework driver to support PartitionDxe changes
This patch reworks the driver to support Partition driver changes. Cc: Eric Dong <eric.d...@intel.com> Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 13 +- .../Universal/Disk/UdfDxe/FileSystemOperations.c | 525 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.c | 7 - MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 88 +--- 4 files changed, 214 insertions(+), 419 deletions(-) diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c index 01361141bb..f2c62967e8 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c @@ -100,6 +100,7 @@ UdfOpenVolume ( >Volume, >Root ); + ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { goto Error_Find_Root_Dir; } @@ -131,7 +132,6 @@ Error_Alloc_Priv_File_Data: CleanupFileInformation (>Root); Error_Find_Root_Dir: - CleanupVolumeInformation (>Volume); Error_Read_Udf_Volume: Error_Invalid_Params: @@ -528,7 +528,6 @@ UdfClose ( EFI_TPL OldTpl; EFI_STATUS Status; PRIVATE_UDF_FILE_DATA *PrivFileData; - PRIVATE_UDF_SIMPLE_FS_DATA *PrivFsData; OldTpl = gBS->RaiseTPL (TPL_CALLBACK); @@ -541,8 +540,6 @@ UdfClose ( PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); - PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs); - if (!PrivFileData->IsRootDirectory) { CleanupFileInformation (>File); @@ -551,10 +548,6 @@ UdfClose ( } } - if (--PrivFsData->OpenFiles == 0) { -CleanupVolumeInformation (>Volume); - } - FreePool ((VOID *)PrivFileData); Exit: @@ -787,7 +780,7 @@ UdfGetInfo ( } else if (CompareGuid (InformationType, )) { String = VolumeLabel; -FileSetDesc = PrivFsData->Volume.FileSetDescs[0]; +FileSetDesc = >Volume.FileSetDesc; OstaCompressed = >LogicalVolumeIdentifier[0]; @@ -846,7 +839,7 @@ UdfGetInfo ( FileSystemInfo->Size= FileSystemInfoLength; FileSystemInfo->ReadOnly= TRUE; FileSystemInfo->BlockSize = - LV_BLOCK_SIZE (>Volume, UDF_DEFAULT_LV_NUM); + PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize; FileSystemInfo->VolumeSize = VolumeSize; FileSystemInfo->FreeSpace = FreeSpaceSize; diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c index 4609580b30..0f4bc02861 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c @@ -60,154 +60,111 @@ FindAnchorVolumeDescriptorPointer ( EFI_STATUS StartMainVolumeDescriptorSequence ( - IN EFI_BLOCK_IO_PROTOCOL *BlockIo, - IN EFI_DISK_IO_PROTOCOL *DiskIo, - IN UDF_ANCHOR_VOLUME_DESCRIPTOR_POINTER *AnchorPoint, - OUT UDF_VOLUME_INFO *Volume + IN EFI_BLOCK_IO_PROTOCOL*BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + OUT UDF_VOLUME_INFO *Volume ) { - EFI_STATUS Status; - UINT32 BlockSize; - UDF_EXTENT_AD *ExtentAd; - UINT64 StartingLsn; - UINT64 EndingLsn; - VOID *Buffer; - UDF_LOGICAL_VOLUME_DESCRIPTOR *LogicalVolDesc; - UDF_PARTITION_DESCRIPTOR *PartitionDesc; - UINTN Index; - UINT32 LogicalBlockSize; + EFI_STATUS Status; + UINT32 BlockSize; + UINT64 BlockOffset; + VOID*Buffer; + UINT32 LogicalBlockSize; + + BlockSize = BlockIo->Media->BlockSize; // - // We've already found an ADVP on the volume. It contains the extent - // (MainVolumeDescriptorSequenceExtent) where the Main Volume Descriptor - // Sequence starts. Therefore, we'll look for Logical Volume Descriptors and - // Partitions Descriptors and save them in memory, accordingly. - // - // Note also that each descriptor will be aligned on a block size (BlockSize) - // boundary, so we need to read one block at a time. + // Allocate buffer for reading disk blocks // - BlockSize= BlockIo->Media->BlockSize; - ExtentAd = >MainVolumeDescriptorSequenceExtent; - StartingLsn = (UINT64)ExtentAd->ExtentLocation; - EndingLsn= StartingLsn + DivU64x32 ( - (UINT64)ExtentAd->ExtentLength, - BlockSize - ); - - Volume->LogicalVolDescs = -
Re: [edk2] [PATCH 0/7] MdeModulePkg/Udf: Code refinements
Hi Hao, On 15/09/2017 01:57, Hao Wu wrote: The series introduces the following code refinements for UdfDxe & PartitionDxe: a. Add checks to ensure no possible NULL pointer dereference b. Reslove operands of different size in bitwise operations c. Use compare operator for non-boolean comparisons d. Refine function description comments e. Refine local variable initialization f. Refine enum members naming style Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Star Zeng <star.z...@intel.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Dandan Bi <dandan...@intel.com> Hao Wu (7): MdeModulePkg/UdfDxe: Add checks to ensure no possible NULL ptr deref MdeModulePkg/UdfDxe: Fix operands of different size in bitwise OP MdeModulePkg/UdfDxe: Use compare operator for non-boolean comparisons MdeModulePkg/Udf: Refine function description comments MdeModulePkg/UdfDxe: Avoid short (single character) variable name MdeModulePkg/Udf: Avoid declaring and initializing local GUID variable MdeModulePkg/UdfDxe: Refine enum member naming style MdeModulePkg/Universal/Disk/PartitionDxe/Udf.c| 20 +- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 5 +- MdeModulePkg/Universal/Disk/UdfDxe/FileName.c | 27 +- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 483 +++- MdeModulePkg/Universal/Disk/UdfDxe/Udf.h | 49 +- 5 files changed, 432 insertions(+), 152 deletions(-) Looks good to me. Also tested it with OVMF X64. Thanks! Reviewed-by: Paulo Alcantara <pca...@zytor.com> Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] Functionality issues in UDF support
Laszlo, On 15/09/2017 12:51, Laszlo Ersek wrote: On 09/15/17 09:38, Ni, Ruiyu wrote: Paulo, Supporting multiple LVDs can be considered as a long-term task, or can be added per request. But I think a urgent fix in PartitionDxe driver is to: 1. create child BLK only for the portion covered by the LVD 2. Do not create child BLK for LVD that's actually an Eltorito LVD I submitted a Bugzilla to record this: https://bugzilla.tianocore.org/show_bug.cgi?id=707 Ray, I've just assigned this bug to myself, for investigation. I think I understand the problem, and the algorithm that's needed for solving the problem is not complex: - iterate over the logical volume descriptors - if the current one is ElTorito, continue iterating - if the current one is not ElTorito, stop, and then install a child for only the portion of the parent BlkIo (using *inclusive* start and stop block numbers) that are covered by the current logical volume descriptor - if no LVD is found that is *not* ElTorito, then install no children, and report failure - future extension: produce children for all non-ElTorito LVDs. The problem is that I have absolutely no knowledge of UDF specifics, and it would take me quite a bit of time to learn enough to actually implement the details for the above algorithm. I don't think this breakage should be allowed to stay in the tree until either I learn enough to fix it, or Paulo finds enough time to write the code (he doesn't have to start learning from zero, but apparently can't find the time to fix the breakage). If I understand correctly, this is exactly the kind of regression that is *not* localized, it messes up the system. Booting from UDF *Bridge* disks is *already* required by the UEFI spec, and it used to work before the UDF-related changes. I will not quote section "13.3.2.1 ISO-9660 and El Torito" of the UEFI-2.7 spec here, because it is confusing; instead I will quote the improved / proposed wording froam Mantis#1835 (I'm at liberty to quote it because I wrote it): I can still boot my Windows 10 ISO image which is an UDF bridge disk image with the UDF changes. With or without UdfDxe driver. The problem is creating UDF child handles that occupy the entire medium instead of a single LVD, hence you can observe the wrong new partition handles & device paths from Ray's mapping out. > A DVD-ROM image formatted as required by the UDF 2.0 specification (OSTA Universal Disk Format Specification, Revision 2.0) shall be booted by UEFI if: - the DVD-ROM image conforms to the "UDF Bridge" format defined in the UDF 2.0 specification, and - the DVD-ROM image contains exactly one ISO-9660 file system, and - the ISO-9660 file system conforms to the "El Torito" Bootable CD-ROM Format Specification. Booting from a DVD-ROM satisfying these requirements is accomplished using the same methods as booting from a CD-ROM: the ISO-9660 file system shall be booted. Again, such disks / disk images could *already* be booted on edk2, before changing PartitionDxe and adding UdfDxe. By introducing the PartitionDxe changes, previous functionality is disturbed. Namely, according to your description at the start of this thread, PartitionInstallUdfChildHandles() creates handles (with BlockIo protocols and device paths) for such volumes -- ElTorito ones -- that are already *owned* by other components in the firmware. In other words, PartitionInstallUdfChildHandles() infringes on the ownership & responsibilities of other components, when there is a UDF *Bridge* volume in the system, which was handled correctly before. > This is the textbook definition of regression. My suggestion is that we disable PartitionInstallUdfChildHandles() entirely, at least temporarily. This should give Paulo enough time to fix the bug *well*. I strongly suggest that we don't try to rush the fix; it could only lead to even more problems. I'm going to submit a patch series that introduces a feature PCD and short-circuits PartitionInstallUdfChildHandles() if the PCD is clear. Since I can't fix it in a pleasant time, as well as it's not a simple fix, that might help us a lot. Thanks! Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] Functionality issues in UDF support
On September 15, 2017 4:10:10 AM GMT-03:00, "Ni, Ruiyu" <ruiyu...@intel.com> wrote: >Paulo, >Can current code support multiple volumes in CDROM? No. It can handle only a single UDF logical volume. I think I never found an UDF disk or image with more than a LVD (Logical Volume Descriptior). Although I think I also added some comment in the code that it currently handles only one logical volume per disk (no access to the code right now, sorry). Other than that, there should be also a DEBUG() or perhaps an ASSERT() in case more than one is found. For supporting multiple logical volumes, we would have to follow your suggestion and change Partition driver to install a child handle for each LVD found in an UDF fs. Thanks! Paulo > >Thanks/Ray > >> -Original Message- >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> Sent: Friday, September 15, 2017 2:26 PM >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; Zeng, >Star >> <star.z...@intel.com> >> Subject: RE: Functionality issues in UDF support >> >> >> >> Ray, >> >> On September 15, 2017 3:02:11 AM GMT-03:00, "Ni, Ruiyu" >> <ruiyu...@intel.com> wrote: >> >Paulo, >> >When will you change the implementation to this way? >> >> Unfortunately I can't promise you when I'd be doing this because, you >know, >> I can only work on this in my free time (very short, ATM). Perhaps >this >> weekend - but real life also happens and I may get preempted by >something >> else. >> >> Paulo >> >> > >> > >> >Thanks/Ray >> > >> >> -Original Message- >> >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> >> Sent: Friday, September 15, 2017 1:38 PM >> >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek ><ler...@redhat.com> >> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; Zeng, >> >Star >> >> <star.z...@intel.com> >> >> Subject: RE: Functionality issues in UDF support >> >> >> >> >> >> >> >> Hi, >> >> >> >> On September 15, 2017 2:08:28 AM GMT-03:00, "Ni, Ruiyu" >> >> <ruiyu...@intel.com> wrote: >> >> >Hi Paulo, >> >> >The responsibility of PartitionDxe driver is to partition the >> >physical >> >> >BLK (the entire CDROM) into logical BLKs (one BLK for each >volume). >> >> >It doesn't make sense to create a child BLK handle which still >> >covers >> >> >the entire CDROM. >> >> >So as I suggested in below, PartitionInstallUdfChildHandles() >should >> >> >contain a for-loop to iterate all the volumes in the CDROM, and >> >create >> >> >child BLK handle for each volumes, but skipping Eltorito volume. >> >> >> >> Ah, makes sense to me now. Thanks for clarifying it. So I agree >with >> >you. >> >> >> >> In whatever you guys decide to do with it, count on me to give >some >> >help. >> >> >> >> Thanks! >> >> Paulo >> >> >> >> > >> >> >Thanks/Ray >> >> > >> >> >> -Original Message- >> >> >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> >> >> Sent: Friday, September 15, 2017 12:58 PM >> >> >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek >> ><ler...@redhat.com> >> >> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; >Zeng, >> >> >Star >> >> >> <star.z...@intel.com> >> >> >> Subject: Re: Functionality issues in UDF support >> >> >> >> >> >> >> >> >> >> >> >> Hi Ray, >> >> >> >> >> >> On September 15, 2017 12:33:04 AM GMT-03:00, "Ni, Ruiyu" >> >> >> <ruiyu...@intel.com> wrote: >> >> >> >Paulo, >> >> >> >Before raising my questions, I'd like to confirm that for a >> >single >> >> >> >CD/DVD in UDF format, there might be multiple volumes. >> >> >> >One of the volume could be Eltorito type. >> >> >> >If my understanding is correct, please continue reading below. >> >> >> >> >> &g
Re: [edk2] [PATCH] MdeModulePkg/UdfDxe: Remove negative comparison of unsigned number
Star, On September 15, 2017 3:14:38 AM GMT-03:00, "Zeng, Star" <star.z...@intel.com> wrote: >Hi, > >Based on recent issues about UDF since the code was pushed for >https://lists.01.org/pipermail/edk2-devel/2017-September/014360.html, I >want to raise some questions kindly. > >https://lists.01.org/pipermail/edk2-devel/2017-September/014409.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014518.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014542.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014489.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014551.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014560.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014649.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014694.html >https://lists.01.org/pipermail/edk2-devel/2017-September/014695.html > >Is the code expected to be got upstream originally? (I may be a stupid >question since the code has been gotten upstream, I just want to double >confirm that as Paulo's reply below "I believed that it would never get >upstream".) >Is the code ready to be in master? Should it be in Staging branch >first? Sorry if I wasn't clear enough, but when I sent UDF support to ML in ~3 years ago, nobody seemed to care and had no feedback since then, so I thought it would never get accepted and then I gave up on trying to improve, cleanup, etc. -- I even started working write support for it but also gave up. It would not make sense to work on it anymore. Right? I would not know to tell you in which branch it should go, but as the driver gives you the ability to access an UDF fs as it's supposed to, then, IMHO, it'd be ready to go either way. > > >Paulo, >Could you help do more evaluation to the code as you said "I *do* know >that the code really needs refactoring, documentation, etc"? I believe >you are most familiar with the code and know its quality. :) > > >BTW: More test seems need to be done before the code check in, for >example, build with various tool chains, ECC scan for coding style, >static tool scan, etc. That is what we(especially me) need to improve >in future when developing and reviewing. >Anyway, let's help keep improving UDF codes. Yep. We should refactor the code, fix coding style issues, improve documetation. Since I was the only one who tested it, it definitely needs a little more testing. With you help, we definitely can resolve all those TODO items. Thanks! Paulo > > > >Thanks, >Star >-Original Message- >From: Paulo Alcantara [mailto:pca...@zytor.com] >Sent: Wednesday, September 13, 2017 1:47 PM >To: Zeng, Star <star.z...@intel.com>; edk2-devel@lists.01.org >Cc: Dong, Eric <eric.d...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>; >Bi, Dandan <dandan...@intel.com> >Subject: RE: [PATCH] MdeModulePkg/UdfDxe: Remove negative comparison of >unsigned number > > > >On September 13, 2017 2:08:54 AM GMT-03:00, "Zeng, Star" ><star.z...@intel.com> wrote: >>I do not understand the context of the code. >>The change is good to fix the build failure, but I want to ask a >>question before I gave Rb. :) >> >>Is it possible ReadFileInfo->FilePosition less than FilePosition? > >Nope. When doing my tests, I briefly looked at code how it's used and >also added an ASSERT() to make sure it is never lesser than >FilePosition. > >BTW, I *do* know that the code really needs refactoring, documentation, >etc. -- I didnt do that before because I believed that it would never >get upstream -- since its now -- I will look forward to that in my free >time. > >Its 2:46am here so I should get some sleep :-) Thanks! > >Paulo > >> >> >>Thanks, >>Star >>-Original Message- >>From: Paulo Alcantara [mailto:pca...@zytor.com] >>Sent: Wednesday, September 13, 2017 12:45 PM >>To: edk2-devel@lists.01.org >>Cc: Paulo Alcantara <pca...@zytor.com>; Zeng, Star >><star.z...@intel.com>; Dong, Eric <eric.d...@intel.com>; Ni, Ruiyu >><ruiyu...@intel.com>; Bi, Dandan <dandan...@intel.com> >>Subject: [PATCH] MdeModulePkg/UdfDxe: Remove negative comparison of >>unsigned number >> >>This patch gets rid of a negative comparison of an UINT64 type >(Offset) >>as it'll never evaluate to true. >> >>Cc: Star Zeng <star.z...@intel.com> >>Cc: Eric Dong <eric.d...@intel.com> >>Cc: Ruiyu Ni <ruiyu...@intel.com> >>Cc: Dandan Bi <dandan...@intel.com> >>Contributed-under: TianoCore Contribution Agreement 1.1 >>Reported-by: Star Zeng <st
Re: [edk2] Functionality issues in UDF support
Ray, On September 15, 2017 3:02:11 AM GMT-03:00, "Ni, Ruiyu" <ruiyu...@intel.com> wrote: >Paulo, >When will you change the implementation to this way? Unfortunately I can't promise you when I'd be doing this because, you know, I can only work on this in my free time (very short, ATM). Perhaps this weekend - but real life also happens and I may get preempted by something else. Paulo > > >Thanks/Ray > >> -----Original Message- >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> Sent: Friday, September 15, 2017 1:38 PM >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; Zeng, >Star >> <star.z...@intel.com> >> Subject: RE: Functionality issues in UDF support >> >> >> >> Hi, >> >> On September 15, 2017 2:08:28 AM GMT-03:00, "Ni, Ruiyu" >> <ruiyu...@intel.com> wrote: >> >Hi Paulo, >> >The responsibility of PartitionDxe driver is to partition the >physical >> >BLK (the entire CDROM) into logical BLKs (one BLK for each volume). >> >It doesn't make sense to create a child BLK handle which still >covers >> >the entire CDROM. >> >So as I suggested in below, PartitionInstallUdfChildHandles() should >> >contain a for-loop to iterate all the volumes in the CDROM, and >create >> >child BLK handle for each volumes, but skipping Eltorito volume. >> >> Ah, makes sense to me now. Thanks for clarifying it. So I agree with >you. >> >> In whatever you guys decide to do with it, count on me to give some >help. >> >> Thanks! >> Paulo >> >> > >> >Thanks/Ray >> > >> >> -Original Message- >> >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> >> Sent: Friday, September 15, 2017 12:58 PM >> >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek ><ler...@redhat.com> >> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; Zeng, >> >Star >> >> <star.z...@intel.com> >> >> Subject: Re: Functionality issues in UDF support >> >> >> >> >> >> >> >> Hi Ray, >> >> >> >> On September 15, 2017 12:33:04 AM GMT-03:00, "Ni, Ruiyu" >> >> <ruiyu...@intel.com> wrote: >> >> >Paulo, >> >> >Before raising my questions, I'd like to confirm that for a >single >> >> >CD/DVD in UDF format, there might be multiple volumes. >> >> >One of the volume could be Eltorito type. >> >> >If my understanding is correct, please continue reading below. >> >> >> >> Right. >> >> >> >> > >> >> >We found below mapping table using "map -r" shell command in a >> >platform >> >> >with only PartitionDxe change and without UdfDxe driver. >> >> >It's a bug that and are created. Actually they >are >> >> >identical to and . >> >> > >> >> >--- Mapping table--- >> >> > BLK2: Alias(s): >> >> > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0) >> >> > >> >> > BLK3: Alias(s): >> >> > >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x0) >> >> > FS1: Alias(s):CD1a65535a1:;BLK4: >> >> > >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x1) >> >> > >> >> > BLK5: Alias(s): >> >> >>PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> >> 1A76-4996-8956-73CDA326CD0A) >> >> > BLK6: Alias(s): >> >> >>PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> >> 1A76-4996-8956-73CDA326CD0A)/CDROM(0x0) >> >> > FS2: Alias(s):CD1a65535ab:;BLK7: >> >> >>PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> >> 1A76- >> >> >4996-8956-73CDA326CD0A)/CDROM(0x1) >> >> >--- End of mapping table --- >> >> > >> >> >After investigation, I found the UDF logic in Partition driver >> >doesn't >> >> >truly skip the Eltorito volume. >> >> >The code flow is like below: >> >> > >> >> > 1. is created by ScsiDiskDxe driver. >> >> > 2. By passing to PartitionDxe Start() >> >> >*and are created
Re: [edk2] Functionality issues in UDF support
Hi, On September 15, 2017 2:08:28 AM GMT-03:00, "Ni, Ruiyu" <ruiyu...@intel.com> wrote: >Hi Paulo, >The responsibility of PartitionDxe driver is to partition the physical >BLK (the entire CDROM) >into logical BLKs (one BLK for each volume). >It doesn't make sense to create a child BLK handle which still covers >the entire CDROM. >So as I suggested in below, PartitionInstallUdfChildHandles() should >contain a for-loop to iterate >all the volumes in the CDROM, and create child BLK handle for each >volumes, but skipping Eltorito volume. Ah, makes sense to me now. Thanks for clarifying it. So I agree with you. In whatever you guys decide to do with it, count on me to give some help. Thanks! Paulo > >Thanks/Ray > >> -Original Message- >> From: Paulo Alcantara [mailto:pca...@zytor.com] >> Sent: Friday, September 15, 2017 12:58 PM >> To: Ni, Ruiyu <ruiyu...@intel.com>; Laszlo Ersek <ler...@redhat.com> >> Cc: edk2-devel@lists.01.org; Wu, Hao A <hao.a...@intel.com>; Zeng, >Star >> <star.z...@intel.com> >> Subject: Re: Functionality issues in UDF support >> >> >> >> Hi Ray, >> >> On September 15, 2017 12:33:04 AM GMT-03:00, "Ni, Ruiyu" >> <ruiyu...@intel.com> wrote: >> >Paulo, >> >Before raising my questions, I'd like to confirm that for a single >> >CD/DVD in UDF format, there might be multiple volumes. >> >One of the volume could be Eltorito type. >> >If my understanding is correct, please continue reading below. >> >> Right. >> >> > >> >We found below mapping table using "map -r" shell command in a >platform >> >with only PartitionDxe change and without UdfDxe driver. >> >It's a bug that and are created. Actually they are >> >identical to and . >> > >> >--- Mapping table--- >> > BLK2: Alias(s): >> > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0) >> > >> > BLK3: Alias(s): >> > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x0) >> > FS1: Alias(s):CD1a65535a1:;BLK4: >> > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x1) >> > >> > BLK5: Alias(s): >> >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> 1A76-4996-8956-73CDA326CD0A) >> > BLK6: Alias(s): >> >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> 1A76-4996-8956-73CDA326CD0A)/CDROM(0x0) >> > FS2: Alias(s):CD1a65535ab:;BLK7: >> >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42- >> 1A76- >> >4996-8956-73CDA326CD0A)/CDROM(0x1) >> >--- End of mapping table --- >> > >> >After investigation, I found the UDF logic in Partition driver >doesn't >> >truly skip the Eltorito volume. >> >The code flow is like below: >> > >> > 1. is created by ScsiDiskDxe driver. >> > 2. By passing to PartitionDxe Start() >> >*and are created by PartitionDxe driver, by >> >PartitionInstallElToritoChildHandles(). >> >*is created by PartitionDxe driver, by >> >PartitionInstallUdfChildHandles(). >> > 3. By passing to PartitionDxe Start() >> >*and are created by PartitionDxe driver, by >> >PartitionInstallElToritoChildHandles(). >> > >> >I think step 2.a is not correct if my understanding to UDF is >correct. >> >The PartitionInstallUdfChildHandles() should iterate all volumes in >the >> >media and creates the child BLK handle for each volume, but skipping >> >Eltorito volume. >> > >> >Instead, the current implementation just creates one child BLK >handle >> >for the entire media. >> >To avoid reclusively creating child BLK handle, the >> >PartitionInstallUdfChildHandles() contains a logic to do nothing >when >> >the handle is created by ParititonDxe driver. The logic is not >needed >> >when the implementation follows my suggestion above. >> >Due to this, step 3.a creates the additional but shouldn't-exist BLK >> >handles and . >> > >> >UdfDxe driver is supposed to Start() on each volume and produce >> >SimpleFileSystem protocol. >> >> It seems that PartitionInstallUdfChildHandles() indeed skips the >ElTorito >> partitions otherwise you'd see the ".../CDROM(0x1)/VenMedia()" and >> ".../CDROM(0x0)/VenMedia()" device paths *also* in the mapping >output. >> >> If I understand correctly, the prob
Re: [edk2] Functionality issues in UDF support
Hi Ray, On September 15, 2017 12:33:04 AM GMT-03:00, "Ni, Ruiyu"wrote: >Paulo, >Before raising my questions, I'd like to confirm that for a single >CD/DVD in UDF format, there might be multiple volumes. >One of the volume could be Eltorito type. >If my understanding is correct, please continue reading below. Right. > >We found below mapping table using "map -r" shell command in a platform >with only PartitionDxe change and without UdfDxe driver. >It's a bug that and are created. Actually they are >identical to and . > >--- Mapping table--- > BLK2: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0) > > BLK3: Alias(s): > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x0) > FS1: Alias(s):CD1a65535a1:;BLK4: > PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/CDROM(0x1) > > BLK5: Alias(s): >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A) > BLK6: Alias(s): >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A)/CDROM(0x0) > FS2: Alias(s):CD1a65535ab:;BLK7: >PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x,0x0)/VenMedia(C5BD4D42-1A76-4996-8956-73CDA326CD0A)/CDROM(0x1) >--- End of mapping table --- > >After investigation, I found the UDF logic in Partition driver doesn't >truly skip the Eltorito volume. >The code flow is like below: > > 1. is created by ScsiDiskDxe driver. > 2. By passing to PartitionDxe Start() >*and are created by PartitionDxe driver, by >PartitionInstallElToritoChildHandles(). >*is created by PartitionDxe driver, by >PartitionInstallUdfChildHandles(). > 3. By passing to PartitionDxe Start() >*and are created by PartitionDxe driver, by >PartitionInstallElToritoChildHandles(). > >I think step 2.a is not correct if my understanding to UDF is correct. >The PartitionInstallUdfChildHandles() should iterate >all volumes in the media and creates the child BLK handle for each >volume, but skipping Eltorito volume. > >Instead, the current implementation just creates one child BLK handle >for the entire media. >To avoid reclusively creating child BLK handle, the >PartitionInstallUdfChildHandles() contains a logic to do nothing when >the handle is created by ParititonDxe driver. The logic is not needed >when the implementation follows my suggestion above. >Due to this, step 3.a creates the additional but shouldn't-exist BLK >handles and . > >UdfDxe driver is supposed to Start() on each volume and produce >SimpleFileSystem protocol. It seems that PartitionInstallUdfChildHandles() indeed skips the ElTorito partitions otherwise you'd see the ".../CDROM(0x1)/VenMedia()" and ".../CDROM(0x0)/VenMedia()" device paths *also* in the mapping output. If I understand correctly, the problem is that when we create a child handle for an UDF volume, Partition driver will execute again, parse the newly created UDF handle, find again an ElTorito partition and then install a new child handle (VenMedia()/CDROM()) So, the logic of skipping of ElTorito partitions in PartitionInstallUdfChildHandles() is not enough. Unfortunately we can't handle UDF bridge disks (ElTorito + UDF) entirely in PartitionInstallUdfChildHandles() -- we should probably also skip UDF device paths in PartitionInstallElToritoChildHandles(). Does it make sense to you, Ray? Thanks for raising this up. Paulo > >Do you agree with my above suggestions? > >Laszlo, >I understood your needs of this UDF support. But as you can see there >are many build failures and even functionality issues due to this >support. >I am not sure how the other open source project handles such cases. >But I am thinking maybe we could move the whole UDF support to >edk2-staging firstly and move it back after all the issues are >resolved. >What's your suggestion? > >Thanks/Ray -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] MdeModulePkg UdfDxe: Fix VS2010/VS2012 build failure
Hi, On 9/14/2017 7:53 AM, Star Zeng wrote: VS2010/VS2012 build failure with below info: warning C4701: potentially uninitialized local variable 'DataOffset' used potentially uninitialized local variable 'FilePosition' used potentially uninitialized local variable 'FinishedSeeking' used potentially uninitialized local variable 'Data' used warning C4703: potentially uninitialized local pointer variable 'Data' used In fact, DataOffset, FilePosition and FinishedSeeking are initialized and then used if (ReadFileInfo->Flags == READ_FILE_SEEK_AND_READ). DoFreeAed will be set to TRUE when Data is allocated and returned from GetAedAdsData(), and Data will be freed if (DoFreeAed) when exiting. Use same method at 5afa5b815936e2b45a375b6521764195bed68680 to fix the build failure. There is related discussion at https://lists.01.org/pipermail/edk2-devel/2017-September/014641.html Cc: Laszlo Ersek <ler...@redhat.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Paulo Alcantara <pca...@zytor.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Liming Gao <liming@intel.com> Cc: Dandan Bi <dandan...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng <star.z...@intel.com> --- MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 4 1 file changed, 4 insertions(+) With your patch, NT32 X64 build passes with VS2012. Thanks! Reviewed-by: Paulo Alcantara <pa...@hp.com> Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] MdeModulePkg/UdfDxe: Fix NULL pointer dereference
On 9/12/2017 8:27 AM, Laszlo Ersek wrote: On 09/12/17 03:30, Paulo Alcantara wrote: REF: https://bugzilla.tianocore.org/show_bug.cgi?id=704 For root directory, the FID (File Identifier Descriptor) pointer is accessible through PRIVATE_UDF_FILE_DATA.Root, whereas non-root directory and regular files, their FIDs are accessible through PRIVATE_UDF_FILE_DATA.File. In UdfSetPosition(), the FID was retrieved through PRIVATE_UDF_FILE_DATA.File, hence when calling it with a root directory, PRIVATE_UDF_FILE_DATA.File.FileIdentifierDescriptor would be NULL and then dereferenced. This patch fixes the NULL pointer dereference by calling _FILE() to transparently return the correct UDF_FILE_INFO * which points to a valid FID descriptor of a specific file. Cc: Star Zeng <star.z...@intel.com> Cc: Eric Dong <eric.d...@intel.com> Cc: Ruiyu Ni <ruiyu...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Steven Shi <steven@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Reported-by: Steven Shi <steven....@intel.com> Signed-off-by: Paulo Alcantara <pca...@zytor.com> --- MdeModulePkg/Universal/Disk/UdfDxe/File.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/File.c b/MdeModulePkg/Universal/Disk/UdfDxe/File.c index 8b9339567f..a1eb2196df 100644 --- a/MdeModulePkg/Universal/Disk/UdfDxe/File.c +++ b/MdeModulePkg/Universal/Disk/UdfDxe/File.c @@ -690,7 +690,8 @@ UdfSetPosition ( PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This); - FileIdentifierDesc = PrivFileData->File.FileIdentifierDesc; + FileIdentifierDesc = _FILE (PrivFileData)->FileIdentifierDesc; + ASSERT (FileIdentifierDesc != NULL); if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) { // // If the file handle is a directory, the _only_ position that may be set is Reviewed-by: Laszlo Ersek <ler...@redhat.com> Ping? :-) Thanks! Paulo ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 0/2] MdeModulePkg: UDF fixes and cleanups, round 2
On September 12, 2017 7:26:10 PM GMT-03:00, Laszlo Ersek <ler...@redhat.com> wrote: >Repo: https://github.com/lersek/edk2.git >Branch: udf_fixes_cleanups_round2 > >Once these patches are sufficiently reviewed, please don't wait for me >to commit them. > >Further UdfDxe issues should be please reported in the TianoCore >Bugzilla. > >Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> >Cc: Eric Dong <eric.d...@intel.com> >Cc: Paulo Alcantara <pca...@zytor.com> >Cc: Ruiyu Ni <ruiyu...@intel.com> >Cc: Star Zeng <star.z...@intel.com> > >Thanks >Laszlo > >Laszlo Ersek (2): > MdeModulePkg/UdfDxe: reject reserved values in ICB.Flags[2:0] > MdeModulePkg/UdfDxe: suppress incorrect compiler warning in ReadFile() > >MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 13 >+ > 1 file changed, 13 insertions(+) Reviewed-by: Paulo Alcantara <pca...@zytor.com> Thanks, Paulo -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH] MdeModulePkg/UdfDxe: Remove negative comparison of unsigned number
On September 13, 2017 2:08:54 AM GMT-03:00, "Zeng, Star" <star.z...@intel.com> wrote: >I do not understand the context of the code. >The change is good to fix the build failure, but I want to ask a >question before I gave Rb. :) > >Is it possible ReadFileInfo->FilePosition less than FilePosition? Nope. When doing my tests, I briefly looked at code how it's used and also added an ASSERT() to make sure it is never lesser than FilePosition. BTW, I *do* know that the code really needs refactoring, documentation, etc. -- I didnt do that before because I believed that it would never get upstream -- since its now -- I will look forward to that in my free time. Its 2:46am here so I should get some sleep :-) Thanks! Paulo > > >Thanks, >Star >-Original Message- >From: Paulo Alcantara [mailto:pca...@zytor.com] >Sent: Wednesday, September 13, 2017 12:45 PM >To: edk2-devel@lists.01.org >Cc: Paulo Alcantara <pca...@zytor.com>; Zeng, Star ><star.z...@intel.com>; Dong, Eric <eric.d...@intel.com>; Ni, Ruiyu ><ruiyu...@intel.com>; Bi, Dandan <dandan...@intel.com> >Subject: [PATCH] MdeModulePkg/UdfDxe: Remove negative comparison of >unsigned number > >This patch gets rid of a negative comparison of an UINT64 type (Offset) >as it'll never evaluate to true. > >Cc: Star Zeng <star.z...@intel.com> >Cc: Eric Dong <eric.d...@intel.com> >Cc: Ruiyu Ni <ruiyu...@intel.com> >Cc: Dandan Bi <dandan...@intel.com> >Contributed-under: TianoCore Contribution Agreement 1.1 >Reported-by: Star Zeng <star.z...@intel.com> >Signed-off-by: Paulo Alcantara <pca...@zytor.com> >--- > MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c | 3 --- > 1 file changed, 3 deletions(-) > >diff --git a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >index 7286265373..2039f80289 100644 >--- a/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >+++ b/MdeModulePkg/Universal/Disk/UdfDxe/FileSystemOperations.c >@@ -1082,9 +1082,6 @@ ReadFile ( > >if (FilePosition + ExtentLength > ReadFileInfo->FilePosition) { > Offset = ReadFileInfo->FilePosition - FilePosition; >- if (Offset < 0) { >-Offset = -(Offset); >- } > } else { > Offset = 0; > } >-- >2.11.0 -- Sent from my Android device with K-9 Mail. Please excuse my brevity. ___ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel