2 Basic command line parser for EBL (Embedded Boot Loader)
\r
4 Copyright (c) 2007, Intel Corporation<BR>
\r
5 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
\r
7 All rights reserved. This program and the accompanying materials
\r
8 are licensed and made available under the terms and conditions of the BSD License
\r
9 which accompanies this distribution. The full text of the license may be found at
\r
10 http://opensource.org/licenses/bsd-license.php
\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
15 Module Name: HwDebug.c
\r
17 Commands useful for debugging hardware.
\r
28 Argv[1] - Hex Address to dump
\r
29 Argv[2] - Number of hex bytes to dump (0x20 is default)
\r
30 Argv[3] - [1|2|4|8] byte width of the dump
\r
32 md 0x123445678 50 4 ; Dump 0x50 4 byte quantities starting at 0x123445678
\r
33 md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
\r
34 md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678
\r
36 @param Argc Number of command arguments in Argv
\r
37 @param Argv Array of strings that represent the parsed command line.
\r
38 Argv[0] is the comamnd name
\r
49 STATIC UINT8 *Address = NULL;
\r
50 STATIC UINTN Length = 0x20;
\r
51 STATIC UINTN Width = 1;
\r
56 Width = AsciiStrHexToUintn(Argv[3]);
\r
58 Length = AsciiStrHexToUintn(Argv[2]);
\r
60 Address = (UINT8 *)AsciiStrHexToUintn(Argv[1]);
\r
65 OutputData(Address, Length, Width, (UINTN)Address);
\r
74 Fill Memory with data
\r
77 Argv[1] - Hex Address to fill
\r
78 Argv[2] - Data to write (0x00 is default)
\r
79 Argv[3] - Number of units to dump.
\r
80 Argv[4] - [1|2|4|8] byte width of the dump
\r
82 mf 0x123445678 aa 1 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
\r
83 mf 0x123445678 aa 4 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
\r
84 mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
\r
85 mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
\r
87 @param Argc Number of command arguments in Argv
\r
88 @param Argv Array of strings that represent the parsed command line.
\r
89 Argv[0] is the comamnd name
\r
107 return EFI_INVALID_PARAMETER;
\r
110 Address = AsciiStrHexToUintn (Argv[1]);
\r
111 Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;
\r
112 Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 4;
\r
113 Length = (Argc > 4) ? AsciiStrHexToUintn (Argv[4]) : 1;
\r
115 for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {
\r
117 MmioWrite32 (Address, Data);
\r
118 } else if (Width == 2) {
\r
119 MmioWrite32 (Address, (UINT16)Data);
\r
121 MmioWrite32 (Address, (UINT8)Data);
\r
125 return EFI_SUCCESS;
\r
130 // Strings for PCI Class code [2]
\r
132 CHAR8 *gPciDevClass[] = {
\r
138 "Memory controller ",
\r
140 "simple communications ",
\r
141 "base system peripherals",
\r
143 "Docking stations ",
\r
149 CHAR8 *gPciSerialClassCodes[] = {
\r
166 @param Argc Number of command arguments in Argv
\r
167 @param Argv Array of strings that represent the parsed command line.
\r
168 Argv[0] is the comamnd name
\r
170 @return EFI_SUCCESS
\r
180 EFI_PCI_IO_PROTOCOL *Pci;
\r
182 EFI_HANDLE *HandleBuffer;
\r
192 PCI_TYPE_GENERIC PciHeader;
\r
193 PCI_TYPE_GENERIC *Header;
\r
194 PCI_BRIDGE_CONTROL_REGISTER *Bridge;
\r
195 PCI_DEVICE_HEADER_TYPE_REGION *Device;
\r
196 PCI_DEVICE_INDEPENDENT_REGION *Hdr;
\r
201 BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;
\r
202 DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;
\r
203 FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;
\r
205 Header = &PciHeader;
\r
207 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
\r
208 if (EFI_ERROR (Status)) {
\r
209 AsciiPrint ("No PCI devices found in the system\n");
\r
210 return EFI_SUCCESS;
\r
214 // Dump all PCI devices
\r
215 AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
\r
216 AsciiPrint ("_____________________________________________________________");
\r
217 for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) {
\r
218 for (Index = 0; Index < HandleCount; Index++) {
\r
219 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
\r
220 if (!EFI_ERROR (Status)) {
\r
221 Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
\r
222 if (ThisBus != Bus) {
\r
225 AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func);
\r
226 Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader);
\r
227 if (!EFI_ERROR (Status)) {
\r
228 Hdr = &PciHeader.Bridge.Hdr;
\r
230 if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) {
\r
231 Str = gPciDevClass[Hdr->ClassCode[2]];
\r
232 if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) {
\r
233 if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) {
\r
234 // print out Firewire or USB inplace of Serial Bus controllers
\r
235 Str = gPciSerialClassCodes[Hdr->ClassCode[1]];
\r
239 Str = "Unknown device ";
\r
241 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);
\r
244 // Only print Segment if it is non zero. If you only have one PCI segment it is
\r
245 // redundent to print it out
\r
246 AsciiPrint (" Seg:%d", Seg);
\r
253 // Dump specific PCI device
\r
254 for (Index = 0; Index < HandleCount; Index++) {
\r
255 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
\r
256 if (!EFI_ERROR (Status)) {
\r
257 Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
\r
258 if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) {
\r
259 // Only print Segment if it is non zero. If you only have one PCI segment it is
\r
260 // redundent to print it out
\r
262 AsciiPrint ("Seg:%d ", Seg);
\r
264 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);
\r
266 Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header);
\r
267 if (!EFI_ERROR (Status)) {
\r
268 Hdr = &PciHeader.Bridge.Hdr;
\r
269 if (IS_PCI_BRIDGE (&PciHeader.Bridge)) {
\r
270 Bridge = &PciHeader.Bridge.Bridge;
\r
272 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
\r
273 Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus
\r
275 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);
\r
277 Device = &PciHeader.Device.Device;
\r
279 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
\r
280 Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID
\r
282 AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]);
\r
283 for (Count = 0; Count < 6; Count++) {
\r
284 AsciiPrint (" Bar %d: 0x%08x\n", Count, Device->Bar[Count]);
\r
296 FreePool (HandleBuffer);
\r
297 return EFI_SUCCESS;
\r
301 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
\r
303 " [bus] [dev] [func]; Dump PCI",
\r
309 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
\r
313 " [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
\r
319 " Addr Len [data] [1|2|4]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
\r
328 Initialize the commands in this in this file
\r
331 EblInitializemdHwDebugCmds (
\r
335 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
\r
336 EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
\r
338 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
\r
339 EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
\r