Mm.c revision f79868cd18238805fe64d2ceca573e7c85ea8146
1/** @file
2  Main file for Mm shell Debug1 function.
3
4  Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
5  This program and the accompanying materials
6  are licensed and made available under the terms and conditions of the BSD License
7  which accompanies this distribution.  The full text of the license may be found at
8  http://opensource.org/licenses/bsd-license.php
9
10  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "UefiShellDebug1CommandsLib.h"
16#include <Library/ShellLib.h>
17#include <Protocol/PciRootBridgeIo.h>
18#include <Protocol/DeviceIo.h>
19
20typedef enum {
21  EfiMemory,
22  EFIMemoryMappedIo,
23  EfiIo,
24  EfiPciConfig,
25  EfiPciEConfig
26} EFI_ACCESS_TYPE;
27
28STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
29  {L"-mmio", TypeFlag},
30  {L"-mem", TypeFlag},
31  {L"-io", TypeFlag},
32  {L"-pci", TypeFlag},
33  {L"-pcie", TypeFlag},
34  {L"-n", TypeFlag},
35  {L"-w", TypeValue},
36  {NULL, TypeMax}
37  };
38
39STATIC CONST UINT64 MaxNum[9]      = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffffULL };
40
41/**
42  Read some data into a buffer from memory.
43
44  @param[in] Width    The width of each read.
45  @param[in] Addresss The memory location to start reading at.
46  @param[in] Size     The size of Buffer in Width sized units.
47  @param[out] Buffer  The buffer to read into.
48**/
49VOID
50EFIAPI
51ReadMem (
52  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
53  IN  UINT64        Address,
54  IN  UINTN         Size,
55  OUT VOID          *Buffer
56  )
57{
58  //
59  // This function is defective.  This ASSERT prevents the defect from affecting anything.
60  //
61  ASSERT(Size == 1);
62  do {
63    if (Width == EfiPciWidthUint8) {
64      *(UINT8 *) Buffer = *(UINT8 *) (UINTN) Address;
65      Address -= 1;
66    } else if (Width == EfiPciWidthUint16) {
67      *(UINT16 *) Buffer = *(UINT16 *) (UINTN) Address;
68      Address -= 2;
69    } else if (Width == EfiPciWidthUint32) {
70      *(UINT32 *) Buffer = *(UINT32 *) (UINTN) Address;
71      Address -= 4;
72    } else if (Width == EfiPciWidthUint64) {
73      *(UINT64 *) Buffer = *(UINT64 *) (UINTN) Address;
74      Address -= 8;
75    } else {
76      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_READ_ERROR), gShellDebug1HiiHandle);
77      break;
78    }
79    Size--;
80  } while (Size > 0);
81}
82
83/**
84  Write some data to memory.
85
86  @param[in] Width    The width of each write.
87  @param[in] Addresss The memory location to start writing at.
88  @param[in] Size     The size of Buffer in Width sized units.
89  @param[in] Buffer   The buffer to write from.
90**/
91VOID
92EFIAPI
93WriteMem (
94  IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
95  IN  UINT64        Address,
96  IN  UINTN         Size,
97  IN  VOID          *Buffer
98  )
99{
100  //
101  // This function is defective.  This ASSERT prevents the defect from affecting anything.
102  //
103  ASSERT(Size == 1);
104  do {
105    if (Width == EfiPciWidthUint8) {
106      *(UINT8 *) (UINTN) Address = *(UINT8 *) Buffer;
107      Address += 1;
108    } else if (Width == EfiPciWidthUint16) {
109      *(UINT16 *) (UINTN) Address = *(UINT16 *) Buffer;
110      Address += 2;
111    } else if (Width == EfiPciWidthUint32) {
112      *(UINT32 *) (UINTN) Address = *(UINT32 *) Buffer;
113      Address += 4;
114    } else if (Width == EfiPciWidthUint64) {
115      *(UINT64 *) (UINTN) Address = *(UINT64 *) Buffer;
116      Address += 8;
117    } else {
118      ASSERT (FALSE);
119    }
120    //
121    //
122    //
123    Size--;
124  } while (Size > 0);
125}
126
127/**
128  Convert a string to it's hex data.
129
130  @param[in] str    The pointer to the string of hex data.
131  @param[out] data  The pointer to the buffer to fill.  Valid upon a TRUE return.
132
133  @retval TRUE      The conversion was successful.
134  @retval FALSE     The conversion failed.
135**/
136BOOLEAN
137EFIAPI
138GetHex (
139  IN  UINT16  *str,
140  OUT UINT64  *data
141  )
142{
143  UINTN   TempUint;
144  CHAR16  TempChar;
145  BOOLEAN Find;
146
147  Find = FALSE;
148  //
149  // convert hex digits
150  //
151  TempUint = 0;
152  TempChar = *(str++);
153  while (TempChar != CHAR_NULL) {
154    if (TempChar >= 'a' && TempChar <= 'f') {
155      TempChar -= 'a' - 'A';
156    }
157
158    if (TempChar == ' ') {
159      break;
160    }
161
162    if ((TempChar >= '0' && TempChar <= '9') || (TempChar >= 'A' && TempChar <= 'F')) {
163      TempUint     = (TempUint << 4) | (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0'));
164
165      Find  = TRUE;
166    } else {
167      return FALSE;
168    }
169
170    TempChar = *(str++);
171  }
172
173  *data = TempUint;
174  return Find;
175}
176
177/**
178  Get the PCI-E Address from a PCI address format 0x0000ssbbddffrrr
179  where ss is SEGMENT, bb is BUS, dd is DEVICE, ff is FUNCTION
180  and rrr is REGISTER (extension format for PCI-E).
181
182  @param[in] InputAddress       PCI address format on input.
183  @param[out]PciEAddress        PCI-E address extention format.
184**/
185VOID
186EFIAPI
187GetPciEAddressFromInputAddress (
188  IN UINT64                 InputAddress,
189  OUT UINT64                *PciEAddress
190  )
191{
192  *PciEAddress = RShiftU64(InputAddress & ~(UINT64) 0xFFF, 4);
193  *PciEAddress += LShiftU64((UINT16) InputAddress & 0x0FFF, 32);
194}
195
196/**
197  Function for 'mm' command.
198
199  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
200  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
201**/
202SHELL_STATUS
203EFIAPI
204ShellCommandRunMm (
205  IN EFI_HANDLE        ImageHandle,
206  IN EFI_SYSTEM_TABLE  *SystemTable
207  )
208{
209  EFI_STATUS                      Status;
210  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
211  UINT64                          Address;
212  UINT64                          PciEAddress;
213  UINT64                          Value;
214  UINT32                          SegmentNumber;
215  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH                    Width;
216  EFI_ACCESS_TYPE                 AccessType;
217  UINT64                          Buffer;
218  UINTN                           Index;
219  UINTN                           Size;
220//  CHAR16                          *ValueStr;
221  BOOLEAN                         Complete;
222  CHAR16                          *InputStr;
223  BOOLEAN                         Interactive;
224  EFI_HANDLE                      *HandleBuffer;
225  UINTN                           BufferSize;
226  UINTN                           ItemValue;
227  LIST_ENTRY                      *Package;
228  CHAR16                          *ProblemParam;
229  SHELL_STATUS                    ShellStatus;
230  CONST CHAR16                    *Temp;
231
232  Address       = 0;
233  PciEAddress   = 0;
234  IoDev         = NULL;
235  HandleBuffer  = NULL;
236  BufferSize    = 0;
237  SegmentNumber = 0;
238  ShellStatus   = SHELL_SUCCESS;
239  InputStr      = NULL;
240
241  //
242  // Parse arguments
243  //
244  Width       = EfiPciWidthUint8;
245  Size        = 1;
246  AccessType  = EfiMemory;
247//  ValueStr    = NULL;
248  Interactive = TRUE;
249  Package     = NULL;
250
251  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
252  if (EFI_ERROR(Status)) {
253    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
254      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
255      FreePool(ProblemParam);
256      ShellStatus = SHELL_INVALID_PARAMETER;
257      goto Done;
258    } else {
259      ASSERT(FALSE);
260    }
261  } else {
262    if (ShellCommandLineGetCount(Package) < 2) {
263      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
264      ShellStatus = SHELL_INVALID_PARAMETER;
265      goto Done;
266    } else if (ShellCommandLineGetCount(Package) > 3) {
267      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
268      ShellStatus = SHELL_INVALID_PARAMETER;
269      goto Done;
270    } else if (ShellCommandLineGetFlag(Package, L"-w") && ShellCommandLineGetValue(Package, L"-w") == NULL) {
271      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"-w");
272      ShellStatus = SHELL_INVALID_PARAMETER;
273      goto Done;
274    } else {
275      if (ShellCommandLineGetFlag(Package, L"-mmio")) {
276        AccessType = EFIMemoryMappedIo;
277        if (ShellCommandLineGetFlag(Package, L"-mem")
278          ||ShellCommandLineGetFlag(Package, L"-io")
279          ||ShellCommandLineGetFlag(Package, L"-pci")
280          ||ShellCommandLineGetFlag(Package, L"-pcie")
281        ){
282          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
283          ShellStatus = SHELL_INVALID_PARAMETER;
284          goto Done;
285        }
286      } else if (ShellCommandLineGetFlag(Package, L"-mem")) {
287        AccessType = EfiMemory;
288        if (ShellCommandLineGetFlag(Package, L"-io")
289          ||ShellCommandLineGetFlag(Package, L"-pci")
290          ||ShellCommandLineGetFlag(Package, L"-pcie")
291        ){
292          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
293          ShellStatus = SHELL_INVALID_PARAMETER;
294          goto Done;
295        }
296      } else if (ShellCommandLineGetFlag(Package, L"-io")) {
297        AccessType = EfiIo;
298        if (ShellCommandLineGetFlag(Package, L"-pci")
299          ||ShellCommandLineGetFlag(Package, L"-pcie")
300        ){
301          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
302          ShellStatus = SHELL_INVALID_PARAMETER;
303          goto Done;
304        }
305      } else if (ShellCommandLineGetFlag(Package, L"-pci")) {
306        AccessType = EfiPciConfig;
307        if (ShellCommandLineGetFlag(Package, L"-pcie")
308        ){
309          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
310          ShellStatus = SHELL_INVALID_PARAMETER;
311          goto Done;
312        }
313      } else if (ShellCommandLineGetFlag(Package, L"-pcie")) {
314        AccessType = EfiPciEConfig;
315      }
316    }
317
318    //
319    // Non interactive for a script file or for the specific parameter
320    //
321    if (gEfiShellProtocol->BatchIsActive() || ShellCommandLineGetFlag (Package, L"-n")) {
322      Interactive = FALSE;
323    }
324
325    Temp = ShellCommandLineGetValue(Package, L"-w");
326    if (Temp != NULL) {
327      ItemValue = ShellStrToUintn (Temp);
328
329      switch (ItemValue) {
330      case 1:
331        Width = EfiPciWidthUint8;
332        Size  = 1;
333        break;
334
335      case 2:
336        Width = EfiPciWidthUint16;
337        Size  = 2;
338        break;
339
340      case 4:
341        Width = EfiPciWidthUint32;
342        Size  = 4;
343        break;
344
345      case 8:
346        Width = EfiPciWidthUint64;
347        Size  = 8;
348        break;
349
350      default:
351        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"-w");
352        ShellStatus = SHELL_INVALID_PARAMETER;
353        goto Done;
354      }
355    }
356
357    Temp = ShellCommandLineGetRawValue(Package, 1);
358    if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, (UINT64*)&Address, TRUE, FALSE))) {
359      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp);
360      ShellStatus = SHELL_INVALID_PARAMETER;
361      goto Done;
362    }
363
364    Temp = ShellCommandLineGetRawValue(Package, 2);
365    if (Temp != NULL) {
366      //
367      // Per spec if value is specified, then -n is assumed.
368      //
369      Interactive = FALSE;
370
371      if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, &Value, TRUE, FALSE))) {
372        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp);
373        ShellStatus = SHELL_INVALID_PARAMETER;
374        goto Done;
375      }
376      switch (Size) {
377      case 1:
378        if (Value > 0xFF) {
379          ShellStatus = SHELL_INVALID_PARAMETER;
380        }
381        break;
382
383      case 2:
384        if (Value > 0xFFFF) {
385          ShellStatus = SHELL_INVALID_PARAMETER;
386        }
387        break;
388
389      case 4:
390        if (Value > 0xFFFFFFFF) {
391          ShellStatus = SHELL_INVALID_PARAMETER;
392        }
393        break;
394
395      default:
396        break;
397      }
398
399      if (ShellStatus != SHELL_SUCCESS) {
400        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp);
401        ShellStatus = SHELL_INVALID_PARAMETER;
402        goto Done;
403      }
404    }
405
406    if ((Address & (Size - 1)) != 0) {
407      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, Address);
408      ShellStatus = SHELL_INVALID_PARAMETER;
409      goto Done;
410    }
411    //
412    // locate DeviceIO protocol interface
413    //
414    if (AccessType != EfiMemory) {
415      Status = gBS->LocateHandleBuffer (
416                 ByProtocol,
417                 &gEfiPciRootBridgeIoProtocolGuid,
418                 NULL,
419                 &BufferSize,
420                 &HandleBuffer
421                );
422      if (EFI_ERROR (Status)) {
423        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle);
424        ShellStatus = SHELL_NOT_FOUND;
425        goto Done;
426      }
427      //
428      // In the case of PCI or PCIE
429      // Get segment number and mask the segment bits in Address
430      //
431      if (AccessType == EfiPciEConfig) {
432        SegmentNumber = (UINT32) RShiftU64 (Address, 36) & 0xff;
433        Address      &= 0xfffffffffULL;
434      } else {
435        if (AccessType == EfiPciConfig) {
436          SegmentNumber = (UINT32) RShiftU64 (Address, 32) & 0xff;
437          Address      &= 0xffffffff;
438        }
439      }
440      //
441      // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment number
442      //
443      for (Index = 0; Index < BufferSize; Index++) {
444        Status = gBS->HandleProtocol (
445                       HandleBuffer[Index],
446                       &gEfiPciRootBridgeIoProtocolGuid,
447                       (VOID *) &IoDev
448                      );
449        if (EFI_ERROR (Status)) {
450          continue;
451        }
452        if (IoDev->SegmentNumber != SegmentNumber) {
453          IoDev = NULL;
454        }
455      }
456      if (IoDev == NULL) {
457        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND), gShellDebug1HiiHandle, SegmentNumber);
458        ShellStatus = SHELL_INVALID_PARAMETER;
459        goto Done;
460      }
461    }
462
463    if (AccessType == EfiIo && Address + Size > 0x10000) {
464      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE), gShellDebug1HiiHandle);
465      ShellStatus = SHELL_INVALID_PARAMETER;
466      goto Done;
467    }
468
469    if (AccessType == EfiPciEConfig) {
470      GetPciEAddressFromInputAddress (Address, &PciEAddress);
471    }
472
473    //
474    // Set value
475    //
476    if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
477      if (AccessType == EFIMemoryMappedIo) {
478        IoDev->Mem.Write (IoDev, Width, Address, 1, &Value);
479      } else if (AccessType == EfiIo) {
480        IoDev->Io.Write (IoDev, Width, Address, 1, &Value);
481      } else if (AccessType == EfiPciConfig) {
482        IoDev->Pci.Write (IoDev, Width, Address, 1, &Value);
483      } else if (AccessType == EfiPciEConfig) {
484        IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Value);
485      } else {
486        WriteMem (Width, Address, 1, &Value);
487      }
488
489      ASSERT(ShellStatus == SHELL_SUCCESS);
490      goto Done;
491    }
492
493
494    //
495    // non-interactive mode
496    //
497    if (!Interactive) {
498      Buffer = 0;
499      if (AccessType == EFIMemoryMappedIo) {
500        if (!gEfiShellProtocol->BatchIsActive()) {
501          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
502        }
503        IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
504      } else if (AccessType == EfiIo) {
505        if (!gEfiShellProtocol->BatchIsActive()) {
506          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
507        }
508        IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
509      } else if (AccessType == EfiPciConfig) {
510        if (!gEfiShellProtocol->BatchIsActive()) {
511          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
512        }
513        IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
514      } else if (AccessType == EfiPciEConfig) {
515        if (!gEfiShellProtocol->BatchIsActive()) {
516          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
517        }
518        IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
519      } else {
520        if (!gEfiShellProtocol->BatchIsActive()) {
521          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
522        }
523        ReadMem (Width, Address, 1, &Buffer);
524      }
525      if (!gEfiShellProtocol->BatchIsActive()) {
526        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
527      }
528      if (Size == 1) {
529        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
530      } else if (Size == 2) {
531        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
532      } else if (Size == 4) {
533        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
534      } else if (Size == 8) {
535        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
536      }
537
538      ShellPrintEx(-1, -1, L"\r\n");
539
540      ASSERT(ShellStatus == SHELL_SUCCESS);
541      goto Done;
542    }
543    //
544    // interactive mode
545    //
546    Complete = FALSE;
547    do {
548      if (AccessType == EfiIo && Address + Size > 0x10000) {
549        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle);
550        break;
551      }
552
553      Buffer = 0;
554      if (AccessType == EFIMemoryMappedIo) {
555        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
556        IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
557      } else if (AccessType == EfiIo) {
558        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
559        IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
560      } else if (AccessType == EfiPciConfig) {
561        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
562        IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
563      } else if (AccessType == EfiPciEConfig) {
564        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
565        IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
566      } else {
567        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
568        ReadMem (Width, Address, 1, &Buffer);
569      }
570
571      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
572
573      if (Size == 1) {
574        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
575      } else if (Size == 2) {
576        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
577      } else if (Size == 4) {
578        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
579      } else if (Size == 8) {
580        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
581      }
582      ShellPrintEx(-1, -1, L" > ");
583      //
584      // wait user input to modify
585      //
586      if (InputStr != NULL) {
587        FreePool(InputStr);
588        InputStr = NULL;
589      }
590      ShellPromptForResponse(ShellPromptResponseTypeFreeform, NULL, (VOID**)&InputStr);
591
592      //
593      // skip space characters
594      //
595      for (Index = 0; InputStr != NULL && InputStr[Index] == ' '; Index++);
596
597      //
598      // parse input string
599      //
600      if (InputStr != NULL && (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q')) {
601        Complete = TRUE;
602      } else if (InputStr == NULL || InputStr[Index] == CHAR_NULL) {
603        //
604        // Continue to next address
605        //
606      } else if (GetHex (InputStr + Index, &Buffer) && Buffer <= MaxNum[Width]) {
607        if (AccessType == EFIMemoryMappedIo) {
608          IoDev->Mem.Write (IoDev, Width, Address, 1, &Buffer);
609        } else if (AccessType == EfiIo) {
610          IoDev->Io.Write (IoDev, Width, Address, 1, &Buffer);
611        } else if (AccessType == EfiPciConfig) {
612          IoDev->Pci.Write (IoDev, Width, Address, 1, &Buffer);
613        } else if (AccessType == EfiPciEConfig) {
614          IoDev->Pci.Write (IoDev, Width, PciEAddress, 1, &Buffer);
615        } else {
616          WriteMem (Width, Address, 1, &Buffer);
617        }
618      } else {
619        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle);
620        continue;
621  //      PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
622      }
623
624      Address += Size;
625      if (AccessType == EfiPciEConfig) {
626        GetPciEAddressFromInputAddress (Address, &PciEAddress);
627      }
628      ShellPrintEx(-1, -1, L"\r\n");
629  //    Print (L"\n");
630    } while (!Complete);
631  }
632  ASSERT(ShellStatus == SHELL_SUCCESS);
633Done:
634
635  if (InputStr != NULL) {
636    FreePool(InputStr);
637  }
638  if (HandleBuffer != NULL) {
639    FreePool (HandleBuffer);
640  }
641  if (Package != NULL) {
642    ShellCommandLineFreeVarList (Package);
643  }
644  return ShellStatus;
645}
646