2 Basic command line parser for EBL (Embedded Boot Loader)
4 Copyright (c) 2007, Intel Corporation<BR>
5 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
7 All rights reserved. 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.
28 Argv[1] - Hex Address to dump
29 Argv[2] - Number of hex bytes to dump (0x20 is default)
30 Argv[3] - [1|2|4|8] byte width of the dump
32 md 0x123445678 50 4 ; 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 comamnd name
49 STATIC UINT8
*Address
= NULL
;
50 STATIC UINTN Length
= 0x20;
51 STATIC UINTN Width
= 1;
56 Width
= AsciiStrHexToUintn(Argv
[3]);
58 Length
= AsciiStrHexToUintn(Argv
[2]);
60 Address
= (UINT8
*)AsciiStrHexToUintn(Argv
[1]);
65 OutputData(Address
, Length
, Width
, (UINTN
)Address
);
77 Argv[1] - Hex Address to fill
78 Argv[2] - Data to write (0x00 is default)
79 Argv[3] - Number of units to dump.
80 Argv[4] - [1|2|4|8] byte width of the dump
82 mf 0x123445678 aa 1 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
83 mf 0x123445678 aa 4 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
84 mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
85 mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
87 @param Argc Number of command arguments in Argv
88 @param Argv Array of strings that represent the parsed command line.
89 Argv[0] is the comamnd name
107 return EFI_INVALID_PARAMETER
;
110 Address
= AsciiStrHexToUintn (Argv
[1]);
111 Data
= (Argc
> 2) ? (UINT32
)AsciiStrHexToUintn (Argv
[2]) : 0;
112 Width
= (Argc
> 3) ? AsciiStrHexToUintn (Argv
[3]) : 4;
113 Length
= (Argc
> 4) ? AsciiStrHexToUintn (Argv
[4]) : 1;
115 for (EndAddress
= Address
+ (Length
* Width
); Address
< EndAddress
; Address
+= Width
) {
117 MmioWrite32 (Address
, Data
);
118 } else if (Width
== 2) {
119 MmioWrite32 (Address
, (UINT16
)Data
);
121 MmioWrite32 (Address
, (UINT8
)Data
);
130 // Strings for PCI Class code [2]
132 CHAR8
*gPciDevClass
[] = {
138 "Memory controller ",
140 "simple communications ",
141 "base system peripherals",
149 CHAR8
*gPciSerialClassCodes
[] = {
166 @param Argc Number of command arguments in Argv
167 @param Argv Array of strings that represent the parsed command line.
168 Argv[0] is the comamnd name
180 EFI_PCI_IO_PROTOCOL
*Pci
;
182 EFI_HANDLE
*HandleBuffer
;
192 PCI_TYPE_GENERIC PciHeader
;
193 PCI_TYPE_GENERIC
*Header
;
194 PCI_BRIDGE_CONTROL_REGISTER
*Bridge
;
195 PCI_DEVICE_HEADER_TYPE_REGION
*Device
;
196 PCI_DEVICE_INDEPENDENT_REGION
*Hdr
;
201 BusArg
= (Argc
> 1) ? AsciiStrDecimalToUintn (Argv
[1]) : 0;
202 DevArg
= (Argc
> 2) ? AsciiStrDecimalToUintn (Argv
[2]) : 0;
203 FuncArg
= (Argc
> 3) ? AsciiStrDecimalToUintn (Argv
[3]) : 0;
207 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPciIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
208 if (EFI_ERROR (Status
)) {
209 AsciiPrint ("No PCI devices found in the system\n");
214 // Dump all PCI devices
215 AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
216 AsciiPrint ("_____________________________________________________________");
217 for (ThisBus
= 0; ThisBus
<= PCI_MAX_BUS
; ThisBus
++) {
218 for (Index
= 0; Index
< HandleCount
; Index
++) {
219 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
220 if (!EFI_ERROR (Status
)) {
221 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
222 if (ThisBus
!= Bus
) {
225 AsciiPrint ("\n%03d.%02d.%02d", Bus
, Dev
, Func
);
226 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), &PciHeader
);
227 if (!EFI_ERROR (Status
)) {
228 Hdr
= &PciHeader
.Bridge
.Hdr
;
230 if (Hdr
->ClassCode
[2] < sizeof (gPciDevClass
)/sizeof (VOID
*)) {
231 Str
= gPciDevClass
[Hdr
->ClassCode
[2]];
232 if (Hdr
->ClassCode
[2] == PCI_CLASS_SERIAL
) {
233 if (Hdr
->ClassCode
[1] < sizeof (gPciSerialClassCodes
)/sizeof (VOID
*)) {
234 // print out Firewire or USB inplace of Serial Bus controllers
235 Str
= gPciSerialClassCodes
[Hdr
->ClassCode
[1]];
239 Str
= "Unknown device ";
241 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr
->VendorId
, Hdr
->DeviceId
, Str
, Hdr
->ClassCode
[1]);
244 // Only print Segment if it is non zero. If you only have one PCI segment it is
245 // redundent to print it out
246 AsciiPrint (" Seg:%d", Seg
);
253 // Dump specific PCI device
254 for (Index
= 0; Index
< HandleCount
; Index
++) {
255 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
**)&Pci
);
256 if (!EFI_ERROR (Status
)) {
257 Pci
->GetLocation (Pci
, &Seg
, &Bus
, &Dev
, &Func
);
258 if ((Bus
== BusArg
) && (Dev
== DevArg
) && (Func
== FuncArg
)) {
259 // Only print Segment if it is non zero. If you only have one PCI segment it is
260 // redundent to print it out
262 AsciiPrint ("Seg:%d ", Seg
);
264 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus
, Dev
, Func
);
266 Status
= Pci
->Pci
.Read (Pci
, EfiPciIoWidthUint32
, 0, sizeof (PciHeader
)/sizeof (UINT32
), Header
);
267 if (!EFI_ERROR (Status
)) {
268 Hdr
= &PciHeader
.Bridge
.Hdr
;
269 if (IS_PCI_BRIDGE (&PciHeader
.Bridge
)) {
270 Bridge
= &PciHeader
.Bridge
.Bridge
;
272 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
273 Bridge
->PrimaryBus
, Bridge
->SecondaryBus
, Bridge
->SubordinateBus
275 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge
->Bar
[0], Bridge
->Bar
[1]);
277 Device
= &PciHeader
.Device
.Device
;
279 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
280 Hdr
->VendorId
, Hdr
->DeviceId
, Device
->SubsystemVendorID
, Device
->SubsystemID
282 AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr
->ClassCode
[2], Hdr
->ClassCode
[1], Hdr
->ClassCode
[0]);
283 for (Count
= 0; Count
< 6; Count
++) {
284 AsciiPrint (" Bar %d: 0x%08x\n", Count
, Device
->Bar
[Count
]);
296 FreePool (HandleBuffer
);
301 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdPciDebugTemplate
[] = {
303 " [bus] [dev] [func]; Dump PCI",
309 GLOBAL_REMOVE_IF_UNREFERENCED
const EBL_COMMAND_TABLE mCmdHwDebugTemplate
[] =
313 " [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
319 " Addr Len [data] [1|2|4]; 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
));