b14d494d5de9d16316639a92904bc24cf9257973
[mirror_edk2.git] / EmbeddedPkg / Ebl / HwDebug.c
1 /** @file
2 Basic command line parser for EBL (Embedded Boot Loader)
3
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6
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
11
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.
14
15 Module Name: HwDebug.c
16
17 Commands useful for debugging hardware.
18
19 **/
20
21 #include "Ebl.h"
22
23
24 /**
25 Dump memory
26
27 Argv[0] - "md"[.#] # is optiona 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)
30
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
34
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 comamnd name
38
39 @return EFI_SUCCESS
40
41 **/
42 EFI_STATUS
43 EblMdCmd (
44 IN UINTN Argc,
45 IN CHAR8 **Argv
46 )
47 {
48 STATIC UINT8 *Address = NULL;
49 STATIC UINTN Length = 0x20;
50 STATIC UINTN Width;
51
52 Width = WidthFromCommandName (Argv[0], 1);
53
54 switch (Argc) {
55 case 3:
56 Length = AsciiStrHexToUintn(Argv[2]);
57 case 2:
58 Address = (UINT8 *)AsciiStrHexToUintn (Argv[1]);
59 default:
60 break;
61 }
62
63 OutputData (Address, Length, Width, (UINTN)Address);
64
65 Address += Length;
66
67 return EFI_SUCCESS;
68 }
69
70
71 /**
72 Fill Memory with data
73
74 Argv[0] - "mfill"[.#] # is optiona 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.
78
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
83
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 comamnd name
87
88 @return EFI_SUCCESS
89
90 **/
91 EFI_STATUS
92 EblMfillCmd (
93 IN UINTN Argc,
94 IN CHAR8 **Argv
95 )
96 {
97 UINTN Address;
98 UINTN EndAddress;
99 UINT32 Data;
100 UINTN Length;
101 UINTN Width;
102
103 if (Argc < 2) {
104 return EFI_INVALID_PARAMETER;
105 }
106
107 Width = WidthFromCommandName (Argv[0], 4);
108
109 Address = AsciiStrHexToUintn (Argv[1]);
110 Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;
111 Length = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1;
112
113 for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {
114 if (Width == 4) {
115 MmioWrite32 (Address, Data);
116 } else if (Width == 2) {
117 MmioWrite16 (Address, (UINT16)Data);
118 } else {
119 MmioWrite8 (Address, (UINT8)Data);
120 }
121 }
122
123 return EFI_SUCCESS;
124 }
125
126
127 //
128 // Strings for PCI Class code [2]
129 //
130 CHAR8 *gPciDevClass[] = {
131 "Old Device ",
132 "Mass storage ",
133 "Network ",
134 "Display ",
135 "Multimedia ",
136 "Memory controller ",
137 "Bridge device ",
138 "simple communications ",
139 "base system peripherals",
140 "Input devices ",
141 "Docking stations ",
142 "Processors ",
143 "serial bus ",
144 };
145
146
147 CHAR8 *gPciSerialClassCodes[] = {
148 "Mass storage ",
149 "Firewire ",
150 "ACCESS bus ",
151 "SSA ",
152 "USB "
153 };
154
155
156 /**
157 PCI Dump
158
159 Argv[0] - "pci"
160 Argv[1] - bus
161 Argv[2] - dev
162 Argv[3] - func
163
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 comamnd name
167
168 @return EFI_SUCCESS
169
170 **/
171 EFI_STATUS
172 EblPciCmd (
173 IN UINTN Argc,
174 IN CHAR8 **Argv
175 )
176 {
177 EFI_STATUS Status;
178 EFI_PCI_IO_PROTOCOL *Pci;
179 UINTN HandleCount;
180 EFI_HANDLE *HandleBuffer;
181 UINTN Seg;
182 UINTN Bus;
183 UINTN Dev;
184 UINTN Func;
185 UINTN BusArg;
186 UINTN DevArg;
187 UINTN FuncArg;
188 UINTN Index;
189 UINTN Count;
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;
195 CHAR8 *Str;
196 UINTN ThisBus;
197
198
199 BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;
200 DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;
201 FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;
202
203 Header = &PciHeader;
204
205 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
206 if (EFI_ERROR (Status)) {
207 AsciiPrint ("No PCI devices found in the system\n");
208 return EFI_SUCCESS;
209 }
210
211 if (Argc == 1) {
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) {
221 continue;
222 }
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;
227
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]];
234 }
235 }
236 } else {
237 Str = "Unknown device ";
238 }
239 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);
240 }
241 if (Seg != 0) {
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);
245 }
246 }
247 }
248 }
249 AsciiPrint ("\n");
250 } else {
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 // redundent to print it out
259 if (Seg != 0) {
260 AsciiPrint ("Seg:%d ", Seg);
261 }
262 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);
263
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;
269 AsciiPrint (
270 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
271 Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus
272 );
273 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);
274 } else {
275 Device = &PciHeader.Device.Device;
276 AsciiPrint (
277 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
278 Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID
279 );
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]);
283 }
284 }
285 }
286
287 AsciiPrint ("\n");
288 break;
289 }
290 }
291 }
292 }
293
294 FreePool (HandleBuffer);
295 return EFI_SUCCESS;
296 }
297
298
299 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
300 "pci",
301 " [bus] [dev] [func]; Dump PCI",
302 NULL,
303 EblPciCmd
304 };
305
306
307 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
308 {
309 {
310 "md",
311 "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
312 NULL,
313 EblMdCmd
314 },
315 {
316 "mfill",
317 "[.{1|2|4}] Addr Len [data]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
318 NULL,
319 EblMfillCmd
320 },
321 };
322
323
324
325 /**
326 Initialize the commands in this in this file
327 **/
328 VOID
329 EblInitializemdHwDebugCmds (
330 VOID
331 )
332 {
333 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
334 EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
335 }
336 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
337 EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
338 }
339 }
340