2 Basic command line parser for EBL (Embedded Boot Loader)
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 Module Name: HwDebug.c
18 Commands useful for debugging hardware.
28 Argv[0] - "md"[.#] # is optional width 1, 2, 4, or 8. Default 1
29 Argv[1] - Hex Address to dump
30 Argv[2] - Number of hex bytes to dump (0x20 is default)
32 md.4 0x123445678 50 ; Dump 0x50 4 byte quantities starting at 0x123445678
33 md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
34 md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678
36 @param Argc Number of command arguments in Argv
37 @param Argv Array of strings that represent the parsed command line.
38 Argv[0] is the command name
50 STATIC UINT8
*Address
= NULL
;
51 STATIC UINTN Length
= 0x20;
54 Width
= WidthFromCommandName (Argv
[0], 1);
58 Length
= AsciiStrHexToUintn(Argv
[2]);
60 Address
= (UINT8
*)AsciiStrHexToUintn (Argv
[1]);
65 OutputData (Address
, Length
, Width
, (UINTN
)Address
);
76 Argv[0] - "mfill"[.#] # is optional width 1, 2, 4, or 8. Default 4
77 Argv[1] - Hex Address to fill
78 Argv[2] - Data to write (0x00 is default)
79 Argv[3] - Number of units to dump.
81 mf.1 0x123445678 aa 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
82 mf.4 0x123445678 aa 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
83 mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
84 mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
86 @param Argc Number of command arguments in Argv
87 @param Argv Array of strings that represent the parsed command line.
88 Argv[0] is the command name
107 return EFI_INVALID_PARAMETER
;
110 Width
= WidthFromCommandName (Argv
[0], 4);
112 Address
= AsciiStrHexToUintn (Argv
[1]);
113 Data
= (Argc
> 2) ? (UINT32
)AsciiStrHexToUintn (Argv
[2]) : 0;
114 Length
= (Argc
> 3) ? AsciiStrHexToUintn (Argv
[3]) : 1;
116 for (EndAddress
= Address
+ (Length
* Width
); Address
< EndAddress
; Address
+= Width
) {
118 MmioWrite32 (Address
, Data
);
119 } else if (Width
== 2) {
120 MmioWrite16 (Address
, (UINT16
)Data
);
122 MmioWrite8 (Address
, (UINT8
)Data
);
131 // Strings for PCI Class code [2]
133 CHAR8
*gPciDevClass
[] = {
139 "Memory controller ",
141 "simple communications ",
142 "base system peripherals",
150 CHAR8
*gPciSerialClassCodes
[] = {
167 @param Argc Number of command arguments in Argv
168 @param Argv Array of strings that represent the parsed command line.
169 Argv[0] is the command name
182 EFI_PCI_IO_PROTOCOL
*Pci
;
184 EFI_HANDLE
*HandleBuffer
;
194 PCI_TYPE_GENERIC PciHeader
;
195 PCI_TYPE_GENERIC
*Header
;
196 PCI_BRIDGE_CONTROL_REGISTER
*Bridge
;
197 PCI_DEVICE_HEADER_TYPE_REGION
*Device
;
198 PCI_DEVICE_INDEPENDENT_REGION
*Hdr
;
203 BusArg
= (Argc
> 1) ? AsciiStrDecimalToUintn (Argv
[1]) : 0;
204 DevArg
= (Argc
> 2) ? AsciiStrDecimalToUintn (Argv
[2]) : 0;
205 FuncArg
= (Argc
> 3) ? AsciiStrDecimalToUintn (Argv
[3]) : 0;
209 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPciIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
210 if (EFI_ERROR (Status
)) {
211 AsciiPrint ("No PCI devices found in the system\n");
216 // Dump all PCI devices
217 AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
218 AsciiPrint ("_____________________________________________________________");
219 for (ThisBus
= 0; ThisBus
<= PCI_MAX_BUS
; ThisBus
++) {
220 for (Index
= 0; Index
< HandleCount
; Index
++) {
221 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
222 if (!EFI_ERROR (Status
)) {
223 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
224 if (ThisBus
!= Bus
) {
227 AsciiPrint ("\n%03d.%02d.%02d", Bus
, Dev
, Func
);
228 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), &PciHeader
);
229 if (!EFI_ERROR (Status
)) {
230 Hdr
= &PciHeader
.Bridge
.Hdr
;
232 if (Hdr
->ClassCode
[2] < sizeof (gPciDevClass
)/sizeof (VOID
*)) {
233 Str
= gPciDevClass
[Hdr
->ClassCode
[2]];
234 if (Hdr
->ClassCode
[2] == PCI_CLASS_SERIAL
) {
235 if (Hdr
->ClassCode
[1] < sizeof (gPciSerialClassCodes
)/sizeof (VOID
*)) {
236 // print out Firewire or USB inplace of Serial Bus controllers
237 Str
= gPciSerialClassCodes
[Hdr
->ClassCode
[1]];
241 Str
= "Unknown device ";
243 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr
->VendorId
, Hdr
->DeviceId
, Str
, Hdr
->ClassCode
[1]);
246 // Only print Segment if it is non zero. If you only have one PCI segment it is
247 // redundent to print it out
248 AsciiPrint (" Seg:%d", Seg
);
255 // Dump specific PCI device
256 for (Index
= 0; Index
< HandleCount
; Index
++) {
257 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
258 if (!EFI_ERROR (Status
)) {
259 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
260 if ((Bus
== BusArg
) && (Dev
== DevArg
) && (Func
== FuncArg
)) {
261 // Only print Segment if it is non zero. If you only have one PCI segment it is
262 // redundant to print it out
264 AsciiPrint ("Seg:%d ", Seg
);
266 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus
, Dev
, Func
);
268 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), Header
);
269 if (!EFI_ERROR (Status
)) {
270 Hdr
= &PciHeader
.Bridge
.Hdr
;
271 if (IS_PCI_BRIDGE (&PciHeader
.Bridge
)) {
272 Bridge
= &PciHeader
.Bridge
.Bridge
;
274 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
275 Bridge
->PrimaryBus
, Bridge
->SecondaryBus
, Bridge
->SubordinateBus
277 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge
->Bar
[0], Bridge
->Bar
[1]);
279 Device
= &PciHeader
.Device
.Device
;
281 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
282 Hdr
->VendorId
, Hdr
->DeviceId
, Device
->SubsystemVendorID
, Device
->SubsystemID
284 AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr
->ClassCode
[2], Hdr
->ClassCode
[1], Hdr
->ClassCode
[0]);
285 for (Count
= 0; Count
< 6; Count
++) {
286 AsciiPrint (" Bar %d: 0x%08x\n", Count
, Device
->Bar
[Count
]);
298 FreePool (HandleBuffer
);
303 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdPciDebugTemplate
[] = {
306 " [bus] [dev] [func]; Dump PCI",
313 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdHwDebugTemplate
[] =
317 "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
323 "[.{1|2|4}] Addr Len [data]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
332 Initialize the commands in this in this file
335 EblInitializemdHwDebugCmds (
339 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd
)) {
340 EblAddCommands (mCmdHwDebugTemplate
, sizeof (mCmdHwDebugTemplate
)/sizeof (EBL_COMMAND_TABLE
));
342 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd
)) {
343 EblAddCommands (mCmdPciDebugTemplate
, sizeof (mCmdPciDebugTemplate
)/sizeof (EBL_COMMAND_TABLE
));