The EFIAPI function declaration is missing for several functions in the EmbeddedPkg/Ebl directory. A few function pointer struct members expect EFIAPI though and GCC46/X64 will fail to compile the directory without them. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Thomas Palmer <thomas.palmer@hpe.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18697 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			347 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			347 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Basic command line parser for EBL (Embedded Boot Loader)
 | |
| 
 | |
|   Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
 | |
|   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 | |
|   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
 | |
| 
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|   Module Name:  HwDebug.c
 | |
| 
 | |
|   Commands useful for debugging hardware.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Ebl.h"
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Dump memory
 | |
| 
 | |
|   Argv[0] - "md"[.#] # is optional width 1, 2, 4, or 8. Default 1
 | |
|   Argv[1] - Hex Address to dump
 | |
|   Argv[2] - Number of hex bytes to dump (0x20 is default)
 | |
| 
 | |
|   md.4 0x123445678 50 ; Dump 0x50 4 byte quantities starting at 0x123445678
 | |
|   md   0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
 | |
|   md   0x123445678    ; Dump 0x20 1 byte quantities starting at 0x123445678
 | |
| 
 | |
|   @param  Argc   Number of command arguments in Argv
 | |
|   @param  Argv   Array of strings that represent the parsed command line.
 | |
|                  Argv[0] is the command name
 | |
| 
 | |
|   @return EFI_SUCCESS
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EblMdCmd (
 | |
|   IN UINTN  Argc,
 | |
|   IN CHAR8  **Argv
 | |
|   )
 | |
| {
 | |
|   STATIC UINT8  *Address = NULL;
 | |
|   STATIC UINTN  Length   = 0x20;
 | |
|   STATIC UINTN  Width;
 | |
| 
 | |
|   Width = WidthFromCommandName (Argv[0], 1);
 | |
| 
 | |
|   switch (Argc) {
 | |
|     case 3:
 | |
|       Length = AsciiStrHexToUintn(Argv[2]);
 | |
|     case 2:
 | |
|       Address = (UINT8 *)AsciiStrHexToUintn (Argv[1]);
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| 
 | |
|   OutputData (Address, Length, Width, (UINTN)Address);
 | |
| 
 | |
|   Address += Length;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Fill Memory with data
 | |
| 
 | |
|   Argv[0] - "mfill"[.#] # is optional width 1, 2, 4, or 8. Default 4
 | |
|   Argv[1] - Hex Address to fill
 | |
|   Argv[2] - Data to write (0x00 is default)
 | |
|   Argv[3] - Number of units to dump.
 | |
| 
 | |
|   mf.1 0x123445678 aa 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
 | |
|   mf.4 0x123445678 aa 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
 | |
|   mf 0x123445678 aa       ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
 | |
|   mf 0x123445678          ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
 | |
| 
 | |
|   @param  Argc   Number of command arguments in Argv
 | |
|   @param  Argv   Array of strings that represent the parsed command line.
 | |
|                  Argv[0] is the command name
 | |
| 
 | |
|   @return EFI_SUCCESS
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EblMfillCmd (
 | |
|   IN UINTN  Argc,
 | |
|   IN CHAR8  **Argv
 | |
|   )
 | |
| {
 | |
|   UINTN   Address;
 | |
|   UINTN   EndAddress;
 | |
|   UINT32  Data;
 | |
|   UINTN   Length;
 | |
|   UINTN   Width;
 | |
| 
 | |
|   if (Argc < 2) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Width = WidthFromCommandName (Argv[0], 4);
 | |
| 
 | |
|   Address = AsciiStrHexToUintn (Argv[1]);
 | |
|   Data    = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;
 | |
|   Length  = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1;
 | |
| 
 | |
|   for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {
 | |
|     if (Width == 4) {
 | |
|       MmioWrite32 (Address, Data);
 | |
|     } else if (Width == 2) {
 | |
|       MmioWrite16 (Address, (UINT16)Data);
 | |
|     } else {
 | |
|       MmioWrite8 (Address, (UINT8)Data);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| //
 | |
| // Strings for PCI Class code [2]
 | |
| //
 | |
| CHAR8 *gPciDevClass[] = {
 | |
|   "Old Device             ",
 | |
|   "Mass storage           ",
 | |
|   "Network                ",
 | |
|   "Display                ",
 | |
|   "Multimedia             ",
 | |
|   "Memory controller      ",
 | |
|   "Bridge device          ",
 | |
|   "simple communications  ",
 | |
|   "base system peripherals",
 | |
|   "Input devices          ",
 | |
|   "Docking stations       ",
 | |
|   "Processors             ",
 | |
|   "serial bus             ",
 | |
| };
 | |
| 
 | |
| 
 | |
| CHAR8 *gPciSerialClassCodes[] = {
 | |
|   "Mass storage           ",
 | |
|   "Firewire               ",
 | |
|   "ACCESS bus             ",
 | |
|   "SSA                    ",
 | |
|   "USB                     "
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   PCI Dump
 | |
| 
 | |
|   Argv[0] - "pci"
 | |
|   Argv[1] - bus
 | |
|   Argv[2] - dev
 | |
|   Argv[3] - func
 | |
| 
 | |
|   @param  Argc   Number of command arguments in Argv
 | |
|   @param  Argv   Array of strings that represent the parsed command line.
 | |
|                  Argv[0] is the command name
 | |
| 
 | |
|   @return EFI_SUCCESS
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EblPciCmd (
 | |
|   IN UINTN  Argc,
 | |
|   IN CHAR8  **Argv
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_PCI_IO_PROTOCOL           *Pci;
 | |
|   UINTN                         HandleCount;
 | |
|   EFI_HANDLE                    *HandleBuffer;
 | |
|   UINTN                         Seg;
 | |
|   UINTN                         Bus;
 | |
|   UINTN                         Dev;
 | |
|   UINTN                         Func;
 | |
|   UINTN                         BusArg;
 | |
|   UINTN                         DevArg;
 | |
|   UINTN                         FuncArg;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         Count;
 | |
|   PCI_TYPE_GENERIC              PciHeader;
 | |
|   PCI_TYPE_GENERIC              *Header;
 | |
|   PCI_BRIDGE_CONTROL_REGISTER   *Bridge;
 | |
|   PCI_DEVICE_HEADER_TYPE_REGION *Device;
 | |
|   PCI_DEVICE_INDEPENDENT_REGION *Hdr;
 | |
|   CHAR8                         *Str;
 | |
|   UINTN                         ThisBus;
 | |
| 
 | |
| 
 | |
|   BusArg  = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;
 | |
|   DevArg  = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;
 | |
|   FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;
 | |
| 
 | |
|   Header = &PciHeader;
 | |
| 
 | |
|   Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     AsciiPrint ("No PCI devices found in the system\n");
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (Argc == 1) {
 | |
|     // Dump all PCI devices
 | |
|     AsciiPrint ("BusDevFun  VendorId DeviceId  Device Class          Sub-Class\n");
 | |
|     AsciiPrint ("_____________________________________________________________");
 | |
|     for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) {
 | |
|       for (Index = 0; Index < HandleCount; Index++) {
 | |
|         Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
 | |
|         if (!EFI_ERROR (Status)) {
 | |
|           Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
 | |
|           if (ThisBus != Bus) {
 | |
|             continue;
 | |
|           }
 | |
|           AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func);
 | |
|           Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader);
 | |
|           if (!EFI_ERROR (Status)) {
 | |
|             Hdr = &PciHeader.Bridge.Hdr;
 | |
| 
 | |
|             if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) {
 | |
|               Str = gPciDevClass[Hdr->ClassCode[2]];
 | |
|               if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) {
 | |
|                 if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) {
 | |
|                   // print out Firewire or USB inplace of Serial Bus controllers
 | |
|                   Str = gPciSerialClassCodes[Hdr->ClassCode[1]];
 | |
|                 }
 | |
|               }
 | |
|             } else {
 | |
|               Str = "Unknown device         ";
 | |
|             }
 | |
|             AsciiPrint ("  0x%04x   0x%04x    %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);
 | |
|           }
 | |
|           if (Seg != 0) {
 | |
|             // Only print Segment if it is non zero. If you only have one PCI segment it is
 | |
|             // redundent to print it out
 | |
|             AsciiPrint (" Seg:%d", Seg);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     AsciiPrint ("\n");
 | |
|   } else {
 | |
|     // Dump specific PCI device
 | |
|     for (Index = 0; Index < HandleCount; Index++) {
 | |
|       Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
 | |
|         if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) {
 | |
|           // Only print Segment if it is non zero. If you only have one PCI segment it is
 | |
|           // redundant to print it out
 | |
|           if (Seg != 0) {
 | |
|             AsciiPrint ("Seg:%d ", Seg);
 | |
|           }
 | |
|           AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);
 | |
| 
 | |
|           Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header);
 | |
|           if (!EFI_ERROR (Status)) {
 | |
|             Hdr = &PciHeader.Bridge.Hdr;
 | |
|             if (IS_PCI_BRIDGE (&PciHeader.Bridge)) {
 | |
|               Bridge = &PciHeader.Bridge.Bridge;
 | |
|               AsciiPrint (
 | |
|                 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
 | |
|                 Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus
 | |
|                 );
 | |
|               AsciiPrint ("  Bar 0: 0x%08x  Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);
 | |
|             } else {
 | |
|               Device = &PciHeader.Device.Device;
 | |
|               AsciiPrint (
 | |
|                 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
 | |
|                 Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID
 | |
|                 );
 | |
|               AsciiPrint ("  Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]);
 | |
|               for (Count = 0; Count < 6; Count++) {
 | |
|                 AsciiPrint ("  Bar %d: 0x%08x\n", Count, Device->Bar[Count]);
 | |
|               }
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           AsciiPrint ("\n");
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool (HandleBuffer);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
 | |
|   {
 | |
|     "pci",
 | |
|     " [bus] [dev] [func]; Dump PCI",
 | |
|     NULL,
 | |
|     EblPciCmd
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
 | |
| {
 | |
|   {
 | |
|     "md",
 | |
|     "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
 | |
|     NULL,
 | |
|     EblMdCmd
 | |
|   },
 | |
|   {
 | |
|     "mfill",
 | |
|     "[.{1|2|4}] Addr Len [data]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
 | |
|     NULL,
 | |
|     EblMfillCmd
 | |
|   },
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize the commands in this in this file
 | |
| **/
 | |
| VOID
 | |
| EblInitializemdHwDebugCmds (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
 | |
|     EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
 | |
|   }
 | |
|   if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
 | |
|     EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
 | |
|   }
 | |
| }
 | |
| 
 |