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>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 Module Name: HwDebug.c
17 Commands useful for debugging hardware.
27 Argv[0] - "md"[.#] # is optional width 1, 2, 4, or 8. Default 1
28 Argv[1] - Hex Address to dump
29 Argv[2] - Number of hex bytes to dump (0x20 is default)
31 md.4 0x123445678 50 ; Dump 0x50 4 byte quantities starting at 0x123445678
32 md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
33 md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678
35 @param Argc Number of command arguments in Argv
36 @param Argv Array of strings that represent the parsed command line.
37 Argv[0] is the command name
48 STATIC UINT8
*Address
= NULL
;
49 STATIC UINTN Length
= 0x20;
52 Width
= WidthFromCommandName (Argv
[0], 1);
56 Length
= AsciiStrHexToUintn(Argv
[2]);
58 Address
= (UINT8
*)AsciiStrHexToUintn (Argv
[1]);
63 OutputData (Address
, Length
, Width
, (UINTN
)Address
);
74 Argv[0] - "mfill"[.#] # is optional width 1, 2, 4, or 8. Default 4
75 Argv[1] - Hex Address to fill
76 Argv[2] - Data to write (0x00 is default)
77 Argv[3] - Number of units to dump.
79 mf.1 0x123445678 aa 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
80 mf.4 0x123445678 aa 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
81 mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
82 mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
84 @param Argc Number of command arguments in Argv
85 @param Argv Array of strings that represent the parsed command line.
86 Argv[0] is the command name
104 return EFI_INVALID_PARAMETER
;
107 Width
= WidthFromCommandName (Argv
[0], 4);
109 Address
= AsciiStrHexToUintn (Argv
[1]);
110 Data
= (Argc
> 2) ? (UINT32
)AsciiStrHexToUintn (Argv
[2]) : 0;
111 Length
= (Argc
> 3) ? AsciiStrHexToUintn (Argv
[3]) : 1;
113 for (EndAddress
= Address
+ (Length
* Width
); Address
< EndAddress
; Address
+= Width
) {
115 MmioWrite32 (Address
, Data
);
116 } else if (Width
== 2) {
117 MmioWrite16 (Address
, (UINT16
)Data
);
119 MmioWrite8 (Address
, (UINT8
)Data
);
128 // Strings for PCI Class code [2]
130 CHAR8
*gPciDevClass
[] = {
136 "Memory controller ",
138 "simple communications ",
139 "base system peripherals",
147 CHAR8
*gPciSerialClassCodes
[] = {
164 @param Argc Number of command arguments in Argv
165 @param Argv Array of strings that represent the parsed command line.
166 Argv[0] is the command name
178 EFI_PCI_IO_PROTOCOL
*Pci
;
180 EFI_HANDLE
*HandleBuffer
;
190 PCI_TYPE_GENERIC PciHeader
;
191 PCI_TYPE_GENERIC
*Header
;
192 PCI_BRIDGE_CONTROL_REGISTER
*Bridge
;
193 PCI_DEVICE_HEADER_TYPE_REGION
*Device
;
194 PCI_DEVICE_INDEPENDENT_REGION
*Hdr
;
199 BusArg
= (Argc
> 1) ? AsciiStrDecimalToUintn (Argv
[1]) : 0;
200 DevArg
= (Argc
> 2) ? AsciiStrDecimalToUintn (Argv
[2]) : 0;
201 FuncArg
= (Argc
> 3) ? AsciiStrDecimalToUintn (Argv
[3]) : 0;
205 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPciIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
206 if (EFI_ERROR (Status
)) {
207 AsciiPrint ("No PCI devices found in the system\n");
212 // Dump all PCI devices
213 AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
214 AsciiPrint ("_____________________________________________________________");
215 for (ThisBus
= 0; ThisBus
<= PCI_MAX_BUS
; ThisBus
++) {
216 for (Index
= 0; Index
< HandleCount
; Index
++) {
217 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
218 if (!EFI_ERROR (Status
)) {
219 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
220 if (ThisBus
!= Bus
) {
223 AsciiPrint ("\n%03d.%02d.%02d", Bus
, Dev
, Func
);
224 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), &PciHeader
);
225 if (!EFI_ERROR (Status
)) {
226 Hdr
= &PciHeader
.Bridge
.Hdr
;
228 if (Hdr
->ClassCode
[2] < sizeof (gPciDevClass
)/sizeof (VOID
*)) {
229 Str
= gPciDevClass
[Hdr
->ClassCode
[2]];
230 if (Hdr
->ClassCode
[2] == PCI_CLASS_SERIAL
) {
231 if (Hdr
->ClassCode
[1] < sizeof (gPciSerialClassCodes
)/sizeof (VOID
*)) {
232 // print out Firewire or USB inplace of Serial Bus controllers
233 Str
= gPciSerialClassCodes
[Hdr
->ClassCode
[1]];
237 Str
= "Unknown device ";
239 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr
->VendorId
, Hdr
->DeviceId
, Str
, Hdr
->ClassCode
[1]);
242 // Only print Segment if it is non zero. If you only have one PCI segment it is
243 // redundent to print it out
244 AsciiPrint (" Seg:%d", Seg
);
251 // Dump specific PCI device
252 for (Index
= 0; Index
< HandleCount
; Index
++) {
253 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
254 if (!EFI_ERROR (Status
)) {
255 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
256 if ((Bus
== BusArg
) && (Dev
== DevArg
) && (Func
== FuncArg
)) {
257 // Only print Segment if it is non zero. If you only have one PCI segment it is
258 // redundant to print it out
260 AsciiPrint ("Seg:%d ", Seg
);
262 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus
, Dev
, Func
);
264 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), Header
);
265 if (!EFI_ERROR (Status
)) {
266 Hdr
= &PciHeader
.Bridge
.Hdr
;
267 if (IS_PCI_BRIDGE (&PciHeader
.Bridge
)) {
268 Bridge
= &PciHeader
.Bridge
.Bridge
;
270 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
271 Bridge
->PrimaryBus
, Bridge
->SecondaryBus
, Bridge
->SubordinateBus
273 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge
->Bar
[0], Bridge
->Bar
[1]);
275 Device
= &PciHeader
.Device
.Device
;
277 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
278 Hdr
->VendorId
, Hdr
->DeviceId
, Device
->SubsystemVendorID
, Device
->SubsystemID
280 AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr
->ClassCode
[2], Hdr
->ClassCode
[1], Hdr
->ClassCode
[0]);
281 for (Count
= 0; Count
< 6; Count
++) {
282 AsciiPrint (" Bar %d: 0x%08x\n", Count
, Device
->Bar
[Count
]);
294 FreePool (HandleBuffer
);
299 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdPciDebugTemplate
[] = {
302 " [bus] [dev] [func]; Dump PCI",
309 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdHwDebugTemplate
[] =
313 "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
319 "[.{1|2|4}] Addr Len [data]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
328 Initialize the commands in this in this file
331 EblInitializemdHwDebugCmds (
335 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd
)) {
336 EblAddCommands (mCmdHwDebugTemplate
, sizeof (mCmdHwDebugTemplate
)/sizeof (EBL_COMMAND_TABLE
));
338 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd
)) {
339 EblAddCommands (mCmdPciDebugTemplate
, sizeof (mCmdPciDebugTemplate
)/sizeof (EBL_COMMAND_TABLE
));