Mm.c revision c011b6c9e2baf57fc0557117e9875ceb3dca55a3
1/** @file
2  Main file for Mm shell Debug1 function.
3
4  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5  Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
6  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
29STATIC 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
40STATIC CONST UINT64 MaxNum[9]      = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffffULL };
41
42/**
43  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 {
77      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_READ_ERROR), gShellDebug1HiiHandle, L"mm");
78      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')) {
164      TempUint     = (TempUint << 4) | (TempChar - (TempChar >= 'A' ? 'A' - 10 : '0'));
165
166      Find  = TRUE;
167    } else {
168      return FALSE;
169    }
170
171    TempChar = *(str++);
172  }
173
174  *data = TempUint;
175  return Find;
176}
177
178/**
179  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;
221//  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
233  Value         = 0;
234  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;
249//  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) {
256      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);
257      FreePool(ProblemParam);
258      ShellStatus = SHELL_INVALID_PARAMETER;
259      goto Done;
260    } else {
261      ASSERT(FALSE);
262    }
263  } else {
264    if (ShellCommandLineGetCount(Package) < 2) {
265      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");
266      ShellStatus = SHELL_INVALID_PARAMETER;
267      goto Done;
268    } else if (ShellCommandLineGetCount(Package) > 3) {
269      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
270      ShellStatus = SHELL_INVALID_PARAMETER;
271      goto Done;
272    } else if (ShellCommandLineGetFlag(Package, L"-w") && ShellCommandLineGetValue(Package, L"-w") == NULL) {
273      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w");
274      ShellStatus = SHELL_INVALID_PARAMETER;
275      goto Done;
276    } else {
277      if (ShellCommandLineGetFlag(Package, L"-mmio")) {
278        AccessType = EFIMemoryMappedIo;
279        if (ShellCommandLineGetFlag(Package, L"-mem")
280          ||ShellCommandLineGetFlag(Package, L"-io")
281          ||ShellCommandLineGetFlag(Package, L"-pci")
282          ||ShellCommandLineGetFlag(Package, L"-pcie")
283        ){
284          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
285          ShellStatus = SHELL_INVALID_PARAMETER;
286          goto Done;
287        }
288      } else if (ShellCommandLineGetFlag(Package, L"-mem")) {
289        AccessType = EfiMemory;
290        if (ShellCommandLineGetFlag(Package, L"-io")
291          ||ShellCommandLineGetFlag(Package, L"-pci")
292          ||ShellCommandLineGetFlag(Package, L"-pcie")
293        ){
294          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
295          ShellStatus = SHELL_INVALID_PARAMETER;
296          goto Done;
297        }
298      } else if (ShellCommandLineGetFlag(Package, L"-io")) {
299        AccessType = EfiIo;
300        if (ShellCommandLineGetFlag(Package, L"-pci")
301          ||ShellCommandLineGetFlag(Package, L"-pcie")
302        ){
303          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
304          ShellStatus = SHELL_INVALID_PARAMETER;
305          goto Done;
306        }
307      } else if (ShellCommandLineGetFlag(Package, L"-pci")) {
308        AccessType = EfiPciConfig;
309        if (ShellCommandLineGetFlag(Package, L"-pcie")
310        ){
311          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
312          ShellStatus = SHELL_INVALID_PARAMETER;
313          goto Done;
314        }
315      } else if (ShellCommandLineGetFlag(Package, L"-pcie")) {
316        AccessType = EfiPciEConfig;
317      }
318    }
319
320    //
321    // Non interactive for a script file or for the specific parameter
322    //
323    if (gEfiShellProtocol->BatchIsActive() || ShellCommandLineGetFlag (Package, L"-n")) {
324      Interactive = FALSE;
325    }
326
327    Temp = ShellCommandLineGetValue(Package, L"-w");
328    if (Temp != NULL) {
329      ItemValue = ShellStrToUintn (Temp);
330
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:
353        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w");
354        ShellStatus = SHELL_INVALID_PARAMETER;
355        goto Done;
356      }
357    }
358
359    Temp = ShellCommandLineGetRawValue(Package, 1);
360    if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, (UINT64*)&Address, TRUE, FALSE))) {
361      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
362      ShellStatus = SHELL_INVALID_PARAMETER;
363      goto Done;
364    }
365
366    Temp = ShellCommandLineGetRawValue(Package, 2);
367    if (Temp != NULL) {
368      //
369      // Per spec if value is specified, then -n is assumed.
370      //
371      Interactive = FALSE;
372
373      if (!ShellIsHexOrDecimalNumber(Temp, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp, &Value, TRUE, FALSE))) {
374        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
375        ShellStatus = SHELL_INVALID_PARAMETER;
376        goto Done;
377      }
378      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) {
402        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
403        ShellStatus = SHELL_INVALID_PARAMETER;
404        goto Done;
405      }
406    }
407
408    if ((Address & (Size - 1)) != 0) {
409      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address);
410      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)) {
425        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");
426        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;
435        Address      &= 0xfffffffffULL;
436      } 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) {
459        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND), gShellDebug1HiiHandle, L"mm", SegmentNumber);
460        ShellStatus = SHELL_INVALID_PARAMETER;
461        goto Done;
462      }
463    }
464
465    if (AccessType == EfiIo && Address + Size > 0x10000) {
466      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm");
467      ShellStatus = SHELL_INVALID_PARAMETER;
468      goto Done;
469    }
470
471    if (AccessType == EfiPciEConfig) {
472      GetPciEAddressFromInputAddress (Address, &PciEAddress);
473    }
474
475    //
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    }
494
495
496    //
497    // non-interactive mode
498    //
499    if (!Interactive) {
500      Buffer = 0;
501      if (AccessType == EFIMemoryMappedIo) {
502        if (!gEfiShellProtocol->BatchIsActive()) {
503          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
504        }
505        IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
506      } else if (AccessType == EfiIo) {
507        if (!gEfiShellProtocol->BatchIsActive()) {
508          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
509        }
510        IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
511      } else if (AccessType == EfiPciConfig) {
512        if (!gEfiShellProtocol->BatchIsActive()) {
513          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
514        }
515        IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
516      } else if (AccessType == EfiPciEConfig) {
517        if (!gEfiShellProtocol->BatchIsActive()) {
518          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
519        }
520        IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
521      } else {
522        if (!gEfiShellProtocol->BatchIsActive()) {
523          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
524        }
525        ReadMem (Width, Address, 1, &Buffer);
526      }
527      if (!gEfiShellProtocol->BatchIsActive()) {
528        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
529      }
530      if (Size == 1) {
531        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
532      } else if (Size == 2) {
533        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
534      } else if (Size == 4) {
535        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
536      } 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) {
551        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm");
552        break;
553      }
554
555      Buffer = 0;
556      if (AccessType == EFIMemoryMappedIo) {
557        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MMIO), gShellDebug1HiiHandle);
558        IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
559      } else if (AccessType == EfiIo) {
560        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_IO), gShellDebug1HiiHandle);
561        IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
562      } else if (AccessType == EfiPciConfig) {
563        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCI), gShellDebug1HiiHandle);
564        IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
565      } else if (AccessType == EfiPciEConfig) {
566        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE), gShellDebug1HiiHandle);
567        IoDev->Pci.Read (IoDev, Width, PciEAddress, 1, &Buffer);
568      } else {
569        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_MEM), gShellDebug1HiiHandle);
570        ReadMem (Width, Address, 1, &Buffer);
571      }
572
573      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
574
575      if (Size == 1) {
576        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF2), gShellDebug1HiiHandle, (UINTN)Buffer);
577      } else if (Size == 2) {
578        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF4), gShellDebug1HiiHandle, (UINTN)Buffer);
579      } else if (Size == 4) {
580        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF8), gShellDebug1HiiHandle, (UINTN)Buffer);
581      } else if (Size == 8) {
582        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_BUF16), gShellDebug1HiiHandle, Buffer);
583      }
584      ShellPrintEx(-1, -1, L" > ");
585      //
586      // wait user input to modify
587      //
588      if (InputStr != NULL) {
589        FreePool(InputStr);
590        InputStr = NULL;
591      }
592      ShellPromptForResponse(ShellPromptResponseTypeFreeform, NULL, (VOID**)&InputStr);
593
594      //
595      // skip space characters
596      //
597      for (Index = 0; InputStr != NULL && InputStr[Index] == ' '; Index++);
598
599      //
600      // parse input string
601      //
602      if (InputStr != NULL && (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q')) {
603        Complete = TRUE;
604      } else if (InputStr == NULL || InputStr[Index] == CHAR_NULL) {
605        //
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 {
621        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");
622        continue;
623  //      PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
624      }
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}
648