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