blob: ca64f2c5b022dc5b8aa49ab11feb4419e01271bb [file] [log] [blame]
jcarsey5d73d922010-11-16 22:36:37 +00001/** @file
2 Main file for Mm shell Debug1 function.
3
Tapan Shahc011b6c2015-02-04 22:25:01 +00004 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
Eric Dong81cd2f52014-06-26 01:38:46 +00005 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
jcarsey5d73d922010-11-16 22:36:37 +00006 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "UefiShellDebug1CommandsLib.h"
17#include <Library/ShellLib.h>
18#include <Protocol/PciRootBridgeIo.h>
19#include <Protocol/DeviceIo.h>
20
21typedef enum {
22 EfiMemory,
23 EFIMemoryMappedIo,
24 EfiIo,
25 EfiPciConfig,
26 EfiPciEConfig
27} EFI_ACCESS_TYPE;
28
jcarsey5d73d922010-11-16 22:36:37 +000029STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
30 {L"-mmio", TypeFlag},
31 {L"-mem", TypeFlag},
32 {L"-io", TypeFlag},
33 {L"-pci", TypeFlag},
34 {L"-pcie", TypeFlag},
35 {L"-n", TypeFlag},
36 {L"-w", TypeValue},
37 {NULL, TypeMax}
38 };
39
andrewfishe0c2cc62011-04-07 21:50:16 +000040STATIC CONST UINT64 MaxNum[9] = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffffULL };
jcarsey5d73d922010-11-16 22:36:37 +000041
42/**
jcarsey3737ac22011-03-25 21:22:20 +000043 Read some data into a buffer from memory.
44
45 @param[in] Width The width of each read.
46 @param[in] Addresss The memory location to start reading at.
47 @param[in] Size The size of Buffer in Width sized units.
48 @param[out] Buffer The buffer to read into.
49**/
50VOID
51EFIAPI
52ReadMem (
53 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
54 IN UINT64 Address,
55 IN UINTN Size,
56 OUT VOID *Buffer
57 )
58{
59 //
60 // This function is defective. This ASSERT prevents the defect from affecting anything.
61 //
62 ASSERT(Size == 1);
63 do {
64 if (Width == EfiPciWidthUint8) {
65 *(UINT8 *) Buffer = *(UINT8 *) (UINTN) Address;
66 Address -= 1;
67 } else if (Width == EfiPciWidthUint16) {
68 *(UINT16 *) Buffer = *(UINT16 *) (UINTN) Address;
69 Address -= 2;
70 } else if (Width == EfiPciWidthUint32) {
71 *(UINT32 *) Buffer = *(UINT32 *) (UINTN) Address;
72 Address -= 4;
73 } else if (Width == EfiPciWidthUint64) {
74 *(UINT64 *) Buffer = *(UINT64 *) (UINTN) Address;
75 Address -= 8;
76 } else {
Tapan Shah4092a8f2015-02-03 21:22:53 +000077 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_READ_ERROR), gShellDebug1HiiHandle, L"mm");
jcarsey3737ac22011-03-25 21:22:20 +000078 break;
79 }
80 Size--;
81 } while (Size > 0);
82}
83
84/**
85 Write some data to memory.
86
87 @param[in] Width The width of each write.
88 @param[in] Addresss The memory location to start writing at.
89 @param[in] Size The size of Buffer in Width sized units.
90 @param[in] Buffer The buffer to write from.
91**/
92VOID
93EFIAPI
94WriteMem (
95 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
96 IN UINT64 Address,
97 IN UINTN Size,
98 IN VOID *Buffer
99 )
100{
101 //
102 // This function is defective. This ASSERT prevents the defect from affecting anything.
103 //
104 ASSERT(Size == 1);
105 do {
106 if (Width == EfiPciWidthUint8) {
107 *(UINT8 *) (UINTN) Address = *(UINT8 *) Buffer;
108 Address += 1;
109 } else if (Width == EfiPciWidthUint16) {
110 *(UINT16 *) (UINTN) Address = *(UINT16 *) Buffer;
111 Address += 2;
112 } else if (Width == EfiPciWidthUint32) {
113 *(UINT32 *) (UINTN) Address = *(UINT32 *) Buffer;
114 Address += 4;
115 } else if (Width == EfiPciWidthUint64) {
116 *(UINT64 *) (UINTN) Address = *(UINT64 *) Buffer;
117 Address += 8;
118 } else {
119 ASSERT (FALSE);
120 }
121 //
122 //
123 //
124 Size--;
125 } while (Size > 0);
126}
127
128/**
129 Convert a string to it's hex data.
130
131 @param[in] str The pointer to the string of hex data.
132 @param[out] data The pointer to the buffer to fill. Valid upon a TRUE return.
133
134 @retval TRUE The conversion was successful.
135 @retval FALSE The conversion failed.
136**/
137BOOLEAN
138EFIAPI
139GetHex (
140 IN UINT16 *str,
141 OUT UINT64 *data
142 )
143{
144 UINTN TempUint;
145 CHAR16 TempChar;
146 BOOLEAN Find;
147
148 Find = FALSE;
149 //
150 // convert hex digits
151 //
152 TempUint = 0;
153 TempChar = *(str++);
154 while (TempChar != CHAR_NULL) {
155 if (TempChar >= 'a' && TempChar <= 'f') {
156 TempChar -= 'a' - 'A';
157 }
158
159 if (TempChar == ' ') {
160 break;
161 }
162
163 if ((TempChar >= '0' && TempChar <= '9') || (TempChar >= 'A' && TempChar <= 'F')) {
jcarseyf3c59712011-04-05 21:19:39 +0000164 TempUint = (TempUint << 4) | (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0'));
jcarsey3737ac22011-03-25 21:22:20 +0000165
166 Find = TRUE;
167 } else {
168 return FALSE;
169 }
170
171 TempChar = *(str++);
172 }
173
174 *data = TempUint;
175 return Find;
176}
177
178/**
jcarsey5d73d922010-11-16 22:36:37 +0000179 Get the PCI-E Address from a PCI address format 0x0000ssbbddffrrr
180 where ss is SEGMENT, bb is BUS, dd is DEVICE, ff is FUNCTION
181 and rrr is REGISTER (extension format for PCI-E).
182
183 @param[in] InputAddress PCI address format on input.
184 @param[out]PciEAddress PCI-E address extention format.
185**/
186VOID
187EFIAPI
188GetPciEAddressFromInputAddress (
189 IN UINT64 InputAddress,
190 OUT UINT64 *PciEAddress
191 )
192{
193 *PciEAddress = RShiftU64(InputAddress & ~(UINT64) 0xFFF, 4);
194 *PciEAddress += LShiftU64((UINT16) InputAddress & 0x0FFF, 32);
195}
196
197/**
198 Function for 'mm' command.
199
200 @param[in] ImageHandle Handle to the Image (NULL if Internal).
201 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
202**/
203SHELL_STATUS
204EFIAPI
205ShellCommandRunMm (
206 IN EFI_HANDLE ImageHandle,
207 IN EFI_SYSTEM_TABLE *SystemTable
208 )
209{
210 EFI_STATUS Status;
211 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
212 UINT64 Address;
213 UINT64 PciEAddress;
214 UINT64 Value;
215 UINT32 SegmentNumber;
216 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width;
217 EFI_ACCESS_TYPE AccessType;
218 UINT64 Buffer;
219 UINTN Index;
220 UINTN Size;
jcarsey5d73d922010-11-16 22:36:37 +0000221// CHAR16 *ValueStr;
222 BOOLEAN Complete;
223 CHAR16 *InputStr;
224 BOOLEAN Interactive;
225 EFI_HANDLE *HandleBuffer;
226 UINTN BufferSize;
227 UINTN ItemValue;
228 LIST_ENTRY *Package;
229 CHAR16 *ProblemParam;
230 SHELL_STATUS ShellStatus;
231 CONST CHAR16 *Temp;
232
Eric Dong81cd2f52014-06-26 01:38:46 +0000233 Value = 0;
jcarsey5d73d922010-11-16 22:36:37 +0000234 Address = 0;
235 PciEAddress = 0;
236 IoDev = NULL;
237 HandleBuffer = NULL;
238 BufferSize = 0;
239 SegmentNumber = 0;
240 ShellStatus = SHELL_SUCCESS;
241 InputStr = NULL;
242
243 //
244 // Parse arguments
245 //
246 Width = EfiPciWidthUint8;
247 Size = 1;
248 AccessType = EfiMemory;
jcarsey5d73d922010-11-16 22:36:37 +0000249// ValueStr = NULL;
250 Interactive = TRUE;
251 Package = NULL;
252
253 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
254 if (EFI_ERROR(Status)) {
255 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000256 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);
jcarsey5d73d922010-11-16 22:36:37 +0000257 FreePool(ProblemParam);
258 ShellStatus = SHELL_INVALID_PARAMETER;
259 goto Done;
260 } else {
261 ASSERT(FALSE);
262 }
263 } else {
jcarsey3737ac22011-03-25 21:22:20 +0000264 if (ShellCommandLineGetCount(Package) < 2) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000265 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000266 ShellStatus = SHELL_INVALID_PARAMETER;
267 goto Done;
268 } else if (ShellCommandLineGetCount(Package) > 3) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000269 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000270 ShellStatus = SHELL_INVALID_PARAMETER;
271 goto Done;
jcarsey3737ac22011-03-25 21:22:20 +0000272 } else if (ShellCommandLineGetFlag(Package, L"-w") && ShellCommandLineGetValue(Package, L"-w") == NULL) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000273 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w");
jcarsey3737ac22011-03-25 21:22:20 +0000274 ShellStatus = SHELL_INVALID_PARAMETER;
275 goto Done;
jcarsey5d73d922010-11-16 22:36:37 +0000276 } else {
277 if (ShellCommandLineGetFlag(Package, L"-mmio")) {
278 AccessType = EFIMemoryMappedIo;
jcarsey3737ac22011-03-25 21:22:20 +0000279 if (ShellCommandLineGetFlag(Package, L"-mem")
280 ||ShellCommandLineGetFlag(Package, L"-io")
281 ||ShellCommandLineGetFlag(Package, L"-pci")
282 ||ShellCommandLineGetFlag(Package, L"-pcie")
283 ){
Tapan Shah4092a8f2015-02-03 21:22:53 +0000284 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
jcarsey3737ac22011-03-25 21:22:20 +0000285 ShellStatus = SHELL_INVALID_PARAMETER;
286 goto Done;
287 }
jcarsey5d73d922010-11-16 22:36:37 +0000288 } else if (ShellCommandLineGetFlag(Package, L"-mem")) {
289 AccessType = EfiMemory;
jcarsey3737ac22011-03-25 21:22:20 +0000290 if (ShellCommandLineGetFlag(Package, L"-io")
291 ||ShellCommandLineGetFlag(Package, L"-pci")
292 ||ShellCommandLineGetFlag(Package, L"-pcie")
293 ){
Tapan Shah4092a8f2015-02-03 21:22:53 +0000294 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
jcarsey3737ac22011-03-25 21:22:20 +0000295 ShellStatus = SHELL_INVALID_PARAMETER;
296 goto Done;
297 }
jcarsey5d73d922010-11-16 22:36:37 +0000298 } else if (ShellCommandLineGetFlag(Package, L"-io")) {
299 AccessType = EfiIo;
jcarsey3737ac22011-03-25 21:22:20 +0000300 if (ShellCommandLineGetFlag(Package, L"-pci")
301 ||ShellCommandLineGetFlag(Package, L"-pcie")
302 ){
Tapan Shah4092a8f2015-02-03 21:22:53 +0000303 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
jcarsey3737ac22011-03-25 21:22:20 +0000304 ShellStatus = SHELL_INVALID_PARAMETER;
305 goto Done;
306 }
jcarsey5d73d922010-11-16 22:36:37 +0000307 } else if (ShellCommandLineGetFlag(Package, L"-pci")) {
308 AccessType = EfiPciConfig;
jcarsey3737ac22011-03-25 21:22:20 +0000309 if (ShellCommandLineGetFlag(Package, L"-pcie")
310 ){
Tapan Shah4092a8f2015-02-03 21:22:53 +0000311 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
jcarsey3737ac22011-03-25 21:22:20 +0000312 ShellStatus = SHELL_INVALID_PARAMETER;
313 goto Done;
314 }
jcarsey5d73d922010-11-16 22:36:37 +0000315 } else if (ShellCommandLineGetFlag(Package, L"-pcie")) {
316 AccessType = EfiPciEConfig;
317 }
318 }
319
Jaben Carseyf79868c2013-11-20 17:25:02 +0000320 //
321 // Non interactive for a script file or for the specific parameter
322 //
323 if (gEfiShellProtocol->BatchIsActive() || ShellCommandLineGetFlag (Package, L"-n")) {
jcarsey5d73d922010-11-16 22:36:37 +0000324 Interactive = FALSE;
325 }
326
327 Temp = ShellCommandLineGetValue(Package, L"-w");
328 if (Temp != NULL) {
jcarsey3737ac22011-03-25 21:22:20 +0000329 ItemValue = ShellStrToUintn (Temp);
jcarsey5d73d922010-11-16 22:36:37 +0000330
331 switch (ItemValue) {
332 case 1:
333 Width = EfiPciWidthUint8;
334 Size = 1;
335 break;
336
337 case 2:
338 Width = EfiPciWidthUint16;
339 Size = 2;
340 break;
341
342 case 4:
343 Width = EfiPciWidthUint32;
344 Size = 4;
345 break;
346
347 case 8:
348 Width = EfiPciWidthUint64;
349 Size = 8;
350 break;
351
352 default:
Tapan Shah4092a8f2015-02-03 21:22:53 +0000353 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w");
jcarsey5d73d922010-11-16 22:36:37 +0000354 ShellStatus = SHELL_INVALID_PARAMETER;
355 goto Done;
356 }
357 }
358
359 Temp = ShellCommandLineGetRawValue(Package, 1);
jcarsey3737ac22011-03-25 21:22:20 +0000360 if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, (UINT64*)&Address, TRUE, FALSE))) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000361 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
jcarsey3737ac22011-03-25 21:22:20 +0000362 ShellStatus = SHELL_INVALID_PARAMETER;
363 goto Done;
jcarsey5d73d922010-11-16 22:36:37 +0000364 }
365
366 Temp = ShellCommandLineGetRawValue(Package, 2);
367 if (Temp != NULL) {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000368 //
369 // Per spec if value is specified, then -n is assumed.
370 //
371 Interactive = FALSE;
372
jcarsey3737ac22011-03-25 21:22:20 +0000373 if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, &Value, TRUE, FALSE))) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000374 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
jcarsey3737ac22011-03-25 21:22:20 +0000375 ShellStatus = SHELL_INVALID_PARAMETER;
376 goto Done;
377 }
jcarsey5d73d922010-11-16 22:36:37 +0000378 switch (Size) {
379 case 1:
380 if (Value > 0xFF) {
381 ShellStatus = SHELL_INVALID_PARAMETER;
382 }
383 break;
384
385 case 2:
386 if (Value > 0xFFFF) {
387 ShellStatus = SHELL_INVALID_PARAMETER;
388 }
389 break;
390
391 case 4:
392 if (Value > 0xFFFFFFFF) {
393 ShellStatus = SHELL_INVALID_PARAMETER;
394 }
395 break;
396
397 default:
398 break;
399 }
400
401 if (ShellStatus != SHELL_SUCCESS) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000402 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
jcarsey5d73d922010-11-16 22:36:37 +0000403 ShellStatus = SHELL_INVALID_PARAMETER;
404 goto Done;
405 }
406 }
407
408 if ((Address & (Size - 1)) != 0) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000409 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address);
jcarsey5d73d922010-11-16 22:36:37 +0000410 ShellStatus = SHELL_INVALID_PARAMETER;
411 goto Done;
412 }
413 //
414 // locate DeviceIO protocol interface
415 //
416 if (AccessType != EfiMemory) {
417 Status = gBS->LocateHandleBuffer (
418 ByProtocol,
419 &gEfiPciRootBridgeIoProtocolGuid,
420 NULL,
421 &BufferSize,
422 &HandleBuffer
423 );
424 if (EFI_ERROR (Status)) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000425 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000426 ShellStatus = SHELL_NOT_FOUND;
427 goto Done;
428 }
429 //
430 // In the case of PCI or PCIE
431 // Get segment number and mask the segment bits in Address
432 //
433 if (AccessType == EfiPciEConfig) {
434 SegmentNumber = (UINT32) RShiftU64 (Address, 36) & 0xff;
andrewfishe0c2cc62011-04-07 21:50:16 +0000435 Address &= 0xfffffffffULL;
jcarsey5d73d922010-11-16 22:36:37 +0000436 } else {
437 if (AccessType == EfiPciConfig) {
438 SegmentNumber = (UINT32) RShiftU64 (Address, 32) & 0xff;
439 Address &= 0xffffffff;
440 }
441 }
442 //
443 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment number
444 //
445 for (Index = 0; Index < BufferSize; Index++) {
446 Status = gBS->HandleProtocol (
447 HandleBuffer[Index],
448 &gEfiPciRootBridgeIoProtocolGuid,
449 (VOID *) &IoDev
450 );
451 if (EFI_ERROR (Status)) {
452 continue;
453 }
454 if (IoDev->SegmentNumber != SegmentNumber) {
455 IoDev = NULL;
456 }
457 }
458 if (IoDev == NULL) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000459 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND), gShellDebug1HiiHandle, L"mm", SegmentNumber);
jcarsey5d73d922010-11-16 22:36:37 +0000460 ShellStatus = SHELL_INVALID_PARAMETER;
461 goto Done;
462 }
463 }
464
465 if (AccessType == EfiIo && Address + Size > 0x10000) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000466 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000467 ShellStatus = SHELL_INVALID_PARAMETER;
468 goto Done;
469 }
470
471 if (AccessType == EfiPciEConfig) {
472 GetPciEAddressFromInputAddress (Address, &PciEAddress);
473 }
474
jcarseya0cd3532011-09-08 16:50:17 +0000475 //
476 // Set value
477 //
478 if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
479 if (AccessType == EFIMemoryMappedIo) {
480 IoDev->Mem.Write (IoDev, Width, Address, 1, &Value);
481 } else if (AccessType == EfiIo) {
482 IoDev->Io.Write (IoDev, Width, Address, 1, &Value);
483 } else if (AccessType == EfiPciConfig) {
484 IoDev->Pci.Write (IoDev, Width, Address, 1, &Value);
485 } else if (AccessType == EfiPciEConfig) {
486 IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Value);
487 } else {
488 WriteMem (Width, Address, 1, &Value);
489 }
490
491 ASSERT(ShellStatus == SHELL_SUCCESS);
492 goto Done;
493 }
jcarsey5d73d922010-11-16 22:36:37 +0000494
495
496 //
497 // non-interactive mode
498 //
499 if (!Interactive) {
500 Buffer = 0;
501 if (AccessType == EFIMemoryMappedIo) {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000502 if (!gEfiShellProtocol->BatchIsActive()) {
503 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
504 }
jcarsey5d73d922010-11-16 22:36:37 +0000505 IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
506 } else if (AccessType == EfiIo) {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000507 if (!gEfiShellProtocol->BatchIsActive()) {
508 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
509 }
jcarsey5d73d922010-11-16 22:36:37 +0000510 IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
511 } else if (AccessType == EfiPciConfig) {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000512 if (!gEfiShellProtocol->BatchIsActive()) {
513 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
514 }
jcarsey5d73d922010-11-16 22:36:37 +0000515 IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
516 } else if (AccessType == EfiPciEConfig) {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000517 if (!gEfiShellProtocol->BatchIsActive()) {
518 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
519 }
jcarsey5d73d922010-11-16 22:36:37 +0000520 IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
521 } else {
Jaben Carseyf79868c2013-11-20 17:25:02 +0000522 if (!gEfiShellProtocol->BatchIsActive()) {
523 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
524 }
jcarsey5d73d922010-11-16 22:36:37 +0000525 ReadMem (Width, Address, 1, &Buffer);
526 }
Jaben Carseyf79868c2013-11-20 17:25:02 +0000527 if (!gEfiShellProtocol->BatchIsActive()) {
528 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
529 }
jcarsey5d73d922010-11-16 22:36:37 +0000530 if (Size == 1) {
ydong10a7e57bd2012-08-07 00:54:29 +0000531 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000532 } else if (Size == 2) {
ydong10a7e57bd2012-08-07 00:54:29 +0000533 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000534 } else if (Size == 4) {
ydong10a7e57bd2012-08-07 00:54:29 +0000535 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000536 } else if (Size == 8) {
537 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
538 }
539
540 ShellPrintEx(-1, -1, L"\r\n");
541
542 ASSERT(ShellStatus == SHELL_SUCCESS);
543 goto Done;
544 }
545 //
546 // interactive mode
547 //
548 Complete = FALSE;
549 do {
550 if (AccessType == EfiIo && Address + Size > 0x10000) {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000551 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000552 break;
553 }
554
555 Buffer = 0;
556 if (AccessType == EFIMemoryMappedIo) {
557 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000558 IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
559 } else if (AccessType == EfiIo) {
560 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000561 IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
562 } else if (AccessType == EfiPciConfig) {
563 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000564 IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
565 } else if (AccessType == EfiPciEConfig) {
566 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000567 IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
568 } else {
569 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000570 ReadMem (Width, Address, 1, &Buffer);
571 }
572
573 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
jcarsey5d73d922010-11-16 22:36:37 +0000574
575 if (Size == 1) {
ydong10a7e57bd2012-08-07 00:54:29 +0000576 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000577 } else if (Size == 2) {
ydong10a7e57bd2012-08-07 00:54:29 +0000578 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000579 } else if (Size == 4) {
ydong10a7e57bd2012-08-07 00:54:29 +0000580 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000581 } else if (Size == 8) {
582 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
jcarsey5d73d922010-11-16 22:36:37 +0000583 }
jcarsey3737ac22011-03-25 21:22:20 +0000584 ShellPrintEx(-1, -1, L" > ");
jcarsey5d73d922010-11-16 22:36:37 +0000585 //
586 // wait user input to modify
587 //
588 if (InputStr != NULL) {
589 FreePool(InputStr);
jcarsey3737ac22011-03-25 21:22:20 +0000590 InputStr = NULL;
jcarsey5d73d922010-11-16 22:36:37 +0000591 }
592 ShellPromptForResponse(ShellPromptResponseTypeFreeform, NULL, (VOID**)&InputStr);
593
594 //
595 // skip space characters
596 //
jcarsey3737ac22011-03-25 21:22:20 +0000597 for (Index = 0; InputStr != NULL && InputStr[Index] == ' '; Index++);
jcarsey5d73d922010-11-16 22:36:37 +0000598
599 //
600 // parse input string
601 //
jcarsey3737ac22011-03-25 21:22:20 +0000602 if (InputStr != NULL && (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q')) {
jcarsey5d73d922010-11-16 22:36:37 +0000603 Complete = TRUE;
jcarsey3737ac22011-03-25 21:22:20 +0000604 } else if (InputStr == NULL || InputStr[Index] == CHAR_NULL) {
jcarsey5d73d922010-11-16 22:36:37 +0000605 //
606 // Continue to next address
607 //
608 } else if (GetHex (InputStr + Index, &Buffer) && Buffer <= MaxNum[Width]) {
609 if (AccessType == EFIMemoryMappedIo) {
610 IoDev->Mem.Write (IoDev, Width, Address, 1, &Buffer);
611 } else if (AccessType == EfiIo) {
612 IoDev->Io.Write (IoDev, Width, Address, 1, &Buffer);
613 } else if (AccessType == EfiPciConfig) {
614 IoDev->Pci.Write (IoDev, Width, Address, 1, &Buffer);
615 } else if (AccessType == EfiPciEConfig) {
616 IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Buffer);
617 } else {
618 WriteMem (Width, Address, 1, &Buffer);
619 }
620 } else {
Tapan Shah4092a8f2015-02-03 21:22:53 +0000621 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");
jcarsey5d73d922010-11-16 22:36:37 +0000622 continue;
jcarsey3737ac22011-03-25 21:22:20 +0000623 // PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
jcarsey5d73d922010-11-16 22:36:37 +0000624 }
625
626 Address += Size;
627 if (AccessType == EfiPciEConfig) {
628 GetPciEAddressFromInputAddress (Address, &PciEAddress);
629 }
630 ShellPrintEx(-1, -1, L"\r\n");
631 // Print (L"\n");
632 } while (!Complete);
633 }
634 ASSERT(ShellStatus == SHELL_SUCCESS);
635Done:
636
637 if (InputStr != NULL) {
638 FreePool(InputStr);
639 }
640 if (HandleBuffer != NULL) {
641 FreePool (HandleBuffer);
642 }
643 if (Package != NULL) {
644 ShellCommandLineFreeVarList (Package);
645 }
646 return ShellStatus;
647}