blob: 226b24500ad4a9fa95d415b59faf337181afece4 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/** @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 optional 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 command name
38
39 @return EFI_SUCCESS
40
41**/
42EFI_STATUS
43EblMdCmd (
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 optional 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 command name
87
88 @return EFI_SUCCESS
89
90**/
91EFI_STATUS
92EblMfillCmd (
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//
130CHAR8 *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
147CHAR8 *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 command name
167
168 @return EFI_SUCCESS
169
170**/
171EFI_STATUS
172EblPciCmd (
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 // redundant 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
299GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
300 {
301 "pci",
302 " [bus] [dev] [func]; Dump PCI",
303 NULL,
304 EblPciCmd
305 }
306};
307
308
309GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
310{
311 {
312 "md",
313 "[.{1|2|4}] [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
314 NULL,
315 EblMdCmd
316 },
317 {
318 "mfill",
319 "[.{1|2|4}] Addr Len [data]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
320 NULL,
321 EblMfillCmd
322 },
323};
324
325
326
327/**
328 Initialize the commands in this in this file
329**/
330VOID
331EblInitializemdHwDebugCmds (
332 VOID
333 )
334{
335 if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
336 EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
337 }
338 if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
339 EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
340 }
341}
342