]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Ebl/HwDebug.c
Update EBL to have an optional width specifier on commands. So hexdump.4 means use...
[mirror_edk2.git] / EmbeddedPkg / Ebl / HwDebug.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Basic command line parser for EBL (Embedded Boot Loader)\r
3\r
4 Copyright (c) 2007, Intel Corporation<BR>\r
5 Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.\r
6\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
11\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
14\r
15 Module Name: HwDebug.c\r
16\r
17 Commands useful for debugging hardware. \r
18\r
19**/\r
20\r
21#include "Ebl.h"\r
22\r
23\r
24/**\r
25 Dump memory\r
26\r
a6d7123e 27 Argv[0] - "md"[.#] # is optiona width 1, 2, 4, or 8. Default 1\r
2ef2b01e
A
28 Argv[1] - Hex Address to dump\r
29 Argv[2] - Number of hex bytes to dump (0x20 is default)\r
2ef2b01e 30\r
a6d7123e 31 md.4 0x123445678 50 ; Dump 0x50 4 byte quantities starting at 0x123445678\r
32 md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678\r
33 md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678\r
2ef2b01e
A
34\r
35 @param Argc Number of command arguments in Argv\r
36 @param Argv Array of strings that represent the parsed command line. \r
37 Argv[0] is the comamnd name\r
38\r
39 @return EFI_SUCCESS\r
40\r
41**/\r
42EFI_STATUS\r
43EblMdCmd (\r
44 IN UINTN Argc,\r
45 IN CHAR8 **Argv\r
46 )\r
47{\r
48 STATIC UINT8 *Address = NULL;\r
49 STATIC UINTN Length = 0x20;\r
a6d7123e 50 STATIC UINTN Width;\r
2ef2b01e 51\r
a6d7123e 52 Width = WidthFromCommandName (Argv[0], 1);\r
53\r
54 switch (Argc) {\r
2ef2b01e
A
55 case 3:\r
56 Length = AsciiStrHexToUintn(Argv[2]);\r
57 case 2:\r
a6d7123e 58 Address = (UINT8 *)AsciiStrHexToUintn (Argv[1]);\r
2ef2b01e
A
59 default:\r
60 break;\r
61 }\r
62\r
a6d7123e 63 OutputData (Address, Length, Width, (UINTN)Address);\r
2ef2b01e
A
64\r
65 Address += Length;\r
66 \r
67 return EFI_SUCCESS;\r
68}\r
69\r
70\r
71/**\r
72 Fill Memory with data\r
73\r
a6d7123e 74 Argv[0] - "mfill"[.#] # is optiona width 1, 2, 4, or 8. Default 4\r
2ef2b01e
A
75 Argv[1] - Hex Address to fill\r
76 Argv[2] - Data to write (0x00 is default)\r
77 Argv[3] - Number of units to dump.\r
2ef2b01e 78\r
a6d7123e 79 mf.1 0x123445678 aa 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes\r
80 mf.4 0x123445678 aa 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes\r
2ef2b01e
A
81 mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte\r
82 mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte\r
83\r
84 @param Argc Number of command arguments in Argv\r
85 @param Argv Array of strings that represent the parsed command line. \r
86 Argv[0] is the comamnd name\r
87\r
88 @return EFI_SUCCESS\r
89\r
90**/\r
91EFI_STATUS\r
92EblMfillCmd (\r
93 IN UINTN Argc,\r
94 IN CHAR8 **Argv\r
95 )\r
96{\r
97 UINTN Address;\r
98 UINTN EndAddress;\r
99 UINT32 Data;\r
100 UINTN Length;\r
101 UINTN Width;\r
102\r
103 if (Argc < 2) {\r
104 return EFI_INVALID_PARAMETER;\r
105 }\r
106\r
a6d7123e 107 Width = WidthFromCommandName (Argv[0], 4);\r
108\r
2ef2b01e
A
109 Address = AsciiStrHexToUintn (Argv[1]);\r
110 Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;\r
a6d7123e 111 Length = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1;\r
2ef2b01e
A
112\r
113 for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {\r
114 if (Width == 4) {\r
115 MmioWrite32 (Address, Data);\r
116 } else if (Width == 2) {\r
117 MmioWrite32 (Address, (UINT16)Data);\r
118 } else {\r
119 MmioWrite32 (Address, (UINT8)Data);\r
120 }\r
121 }\r
122 \r
123 return EFI_SUCCESS;\r
124}\r
125\r
126\r
127//\r
128// Strings for PCI Class code [2]\r
129//\r
130CHAR8 *gPciDevClass[] = {\r
131 "Old Device ",\r
132 "Mass storage ",\r
133 "Network ",\r
134 "Display ",\r
135 "Multimedia ",\r
136 "Memory controller ",\r
137 "Bridge device ",\r
138 "simple communications ",\r
139 "base system peripherals",\r
140 "Input devices ",\r
141 "Docking stations ",\r
142 "Processors ",\r
143 "serial bus ",\r
144};\r
145\r
146\r
147CHAR8 *gPciSerialClassCodes[] = {\r
148 "Mass storage ",\r
149 "Firewire ",\r
150 "ACCESS bus ",\r
151 "SSA ",\r
152 "USB "\r
153};\r
154\r
155\r
156/**\r
157 PCI Dump\r
158\r
159 Argv[0] - "pci"\r
160 Argv[1] - bus\r
161 Argv[2] - dev\r
162 Argv[3] - func\r
163\r
164 @param Argc Number of command arguments in Argv\r
165 @param Argv Array of strings that represent the parsed command line. \r
166 Argv[0] is the comamnd name\r
167\r
168 @return EFI_SUCCESS\r
169\r
170**/\r
171EFI_STATUS\r
172EblPciCmd (\r
173 IN UINTN Argc,\r
174 IN CHAR8 **Argv\r
175 )\r
176{\r
177 EFI_STATUS Status;\r
178 EFI_PCI_IO_PROTOCOL *Pci;\r
179 UINTN HandleCount;\r
180 EFI_HANDLE *HandleBuffer;\r
181 UINTN Seg;\r
182 UINTN Bus;\r
183 UINTN Dev;\r
184 UINTN Func;\r
185 UINTN BusArg;\r
186 UINTN DevArg;\r
187 UINTN FuncArg;\r
188 UINTN Index;\r
189 UINTN Count;\r
190 PCI_TYPE_GENERIC PciHeader;\r
191 PCI_TYPE_GENERIC *Header;\r
192 PCI_BRIDGE_CONTROL_REGISTER *Bridge;\r
193 PCI_DEVICE_HEADER_TYPE_REGION *Device;\r
194 PCI_DEVICE_INDEPENDENT_REGION *Hdr;\r
195 CHAR8 *Str;\r
196 UINTN ThisBus;\r
197\r
198 \r
199 BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;\r
200 DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;\r
201 FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;\r
202\r
203 Header = &PciHeader;\r
204 \r
205 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);\r
206 if (EFI_ERROR (Status)) {\r
207 AsciiPrint ("No PCI devices found in the system\n");\r
208 return EFI_SUCCESS;\r
209 }\r
210\r
211 if (Argc == 1) {\r
212 // Dump all PCI devices\r
213 AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");\r
214 AsciiPrint ("_____________________________________________________________");\r
215 for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) {\r
216 for (Index = 0; Index < HandleCount; Index++) {\r
217 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);\r
218 if (!EFI_ERROR (Status)) {\r
219 Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);\r
220 if (ThisBus != Bus) {\r
221 continue;\r
222 }\r
223 AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func);\r
224 Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader);\r
225 if (!EFI_ERROR (Status)) {\r
226 Hdr = &PciHeader.Bridge.Hdr;\r
227 \r
228 if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) {\r
229 Str = gPciDevClass[Hdr->ClassCode[2]];\r
230 if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) {\r
231 if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) {\r
232 // print out Firewire or USB inplace of Serial Bus controllers\r
233 Str = gPciSerialClassCodes[Hdr->ClassCode[1]];\r
234 }\r
235 }\r
236 } else {\r
237 Str = "Unknown device ";\r
238 }\r
239 AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);\r
240 }\r
241 if (Seg != 0) {\r
242 // Only print Segment if it is non zero. If you only have one PCI segment it is \r
243 // redundent to print it out\r
244 AsciiPrint (" Seg:%d", Seg);\r
245 }\r
246 }\r
247 }\r
248 }\r
249 AsciiPrint ("\n");\r
250 } else {\r
251 // Dump specific PCI device\r
252 for (Index = 0; Index < HandleCount; Index++) {\r
253 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);\r
254 if (!EFI_ERROR (Status)) {\r
255 Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);\r
256 if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) {\r
257 // Only print Segment if it is non zero. If you only have one PCI segment it is \r
258 // redundent to print it out\r
259 if (Seg != 0) {\r
260 AsciiPrint ("Seg:%d ", Seg);\r
261 }\r
262 AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);\r
263 \r
264 Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header);\r
265 if (!EFI_ERROR (Status)) {\r
266 Hdr = &PciHeader.Bridge.Hdr;\r
267 if (IS_PCI_BRIDGE (&PciHeader.Bridge)) {\r
268 Bridge = &PciHeader.Bridge.Bridge;\r
269 AsciiPrint (\r
270 "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n", \r
271 Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus\r
272 );\r
273 AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);\r
274 } else {\r
275 Device = &PciHeader.Device.Device;\r
276 AsciiPrint (\r
277 "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",\r
278 Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID\r
279 );\r
280 AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]);\r
281 for (Count = 0; Count < 6; Count++) {\r
282 AsciiPrint (" Bar %d: 0x%08x\n", Count, Device->Bar[Count]);\r
283 }\r
284 }\r
285 }\r
286 \r
287 AsciiPrint ("\n");\r
288 break;\r
289 }\r
290 }\r
291 }\r
292 }\r
293 \r
294 FreePool (HandleBuffer);\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298\r
299GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {\r
300 "pci",\r
301 " [bus] [dev] [func]; Dump PCI",\r
302 NULL,\r
303 EblPciCmd\r
304};\r
305\r
306\r
307GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =\r
308{\r
309 {\r
310 "md",\r
a6d7123e 311 "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",\r
2ef2b01e
A
312 NULL,\r
313 EblMdCmd\r
314 },\r
315 {\r
316 "mfill",\r
a6d7123e 317 "[.{1|2|4}] Addr Len [data] [1|2|4]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",\r
2ef2b01e
A
318 NULL,\r
319 EblMfillCmd\r
320 },\r
321};\r
322\r
323\r
324\r
325/**\r
326 Initialize the commands in this in this file\r
327**/\r
328VOID\r
329EblInitializemdHwDebugCmds (\r
330 VOID\r
331 )\r
332{\r
333 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {\r
334 EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));\r
335 }\r
336 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {\r
337 EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));\r
338 }\r
339}\r
340\r