20500097317c8b5014e8a16dbc1ed13750b782dc
[efi/shell/.git] / mm / mm.c
1 /*++
2
3 Copyright (c) 2005, Intel Corporation                                                         
4 All rights reserved. This program and the accompanying materials                          
5 are licensed and made available under the terms and conditions of the BSD License         
6 which accompanies this distribution. The full text of the license may be found at         
7 http://opensource.org/licenses/bsd-license.php                                            
8                                                                                           
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
11
12 Module Name: 
13
14   mm.c
15   
16 Abstract: 
17
18   shell command "mm". Modify memory/IO/PCI/MMIO.
19
20 Revision History
21
22 --*/
23
24 #include "EfiShellLib.h"
25 #include "mm.h"
26
27 extern UINT8  STRING_ARRAY_NAME[];
28
29 //
30 // This is the generated header file which includes whatever needs to be exported (strings + IFR)
31 //
32 #include STRING_DEFINES_FILE
33
34 #include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
35
36 typedef enum {
37   EfiMemory,
38   EFIMemoryMappedIo,
39   EfiIo,
40   EfiPciConfig
41 } EFI_ACCESS_TYPE;
42
43 EFI_STATUS
44 DumpIoModify (
45   IN EFI_HANDLE           ImageHandle,
46   IN EFI_SYSTEM_TABLE     *SystemTable
47   );
48
49 VOID
50 ReadMem (
51   IN  EFI_IO_WIDTH  Width,
52   IN  UINT64        Address,
53   IN  UINTN         Size,
54   IN  VOID          *Buffer
55   );
56
57 VOID
58 WriteMem (
59   IN  EFI_IO_WIDTH  Width,
60   IN  UINT64        Address,
61   IN  UINTN         Size,
62   IN  VOID          *Buffer
63   );
64
65 STATIC
66 BOOLEAN
67 GetHex (
68   IN  UINT16  *str,
69   OUT UINT64  *data
70   );
71
72 //
73 // Global Variables
74 //
75 EFI_HII_HANDLE HiiHandle;
76 EFI_GUID EfiIomodGuid = EFI_IOMOD_GUID;
77 SHELL_VAR_CHECK_ITEM    IomodCheckList[] = {
78   {
79     L"-MMIO",
80     0x01,
81     0x0E,
82     FlagTypeSingle
83   },
84   {
85     L"-MEM",
86     0x02,
87     0x0D,
88     FlagTypeSingle
89   },
90   {
91     L"-IO",
92     0x04,
93     0x0B,
94     FlagTypeSingle
95   },
96   {
97     L"-PCI",
98     0x08,
99     0x07,
100     FlagTypeSingle
101   },
102   {
103     L"-w",
104     0x10,
105     0,
106     FlagTypeNeedVar
107   },
108   {
109     L"-n",
110     0x20,
111     0,
112     FlagTypeSingle
113   },
114   {
115     L"-b",
116     0x40,
117     0,
118     FlagTypeSingle
119   },
120   {
121     L"-?",
122     0x80,
123     0,
124     FlagTypeSingle
125   },
126   {
127     NULL,
128     0,
129     0,
130     0
131   }
132 };
133
134 UINT64 MaxNum[9]      = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffff };
135
136 EFI_BOOTSHELL_CODE(
137   EFI_APPLICATION_ENTRY_POINT(DumpIoModify)
138 )
139
140 EFI_STATUS
141 OldShellParserMM (
142   OUT EFI_IO_WIDTH       *Width,
143   OUT EFI_ACCESS_TYPE    *AccessType,
144   OUT UINT64             *Address,
145   OUT UINT64             *Value,
146   OUT UINTN              *Size,
147   OUT BOOLEAN            *Interactive,
148   OUT CHAR16             **ValueStr
149   );
150
151 EFI_STATUS
152 DumpIoModify (
153   IN EFI_HANDLE           ImageHandle,
154   IN EFI_SYSTEM_TABLE     *SystemTable
155   )
156 /*++
157
158 Routine Description:
159   Dump or modify MEM/IO/PCI/MMIO.
160
161 Arguments:
162   ImageHandle     The image handle. 
163   SystemTable     The system table.
164
165 Returns:
166   EFI_SUCCESS             - Command completed successfully
167   EFI_INVALID_PARAMETER   - Command usage error
168
169 Notes:
170   For Shell Mode 1.1.1:
171   MM Address [Width] [;[MEM | MMIO | IO | PCI]] [:Value]
172     1|2|4|8 supported byte widths - Default is 1 byte. 
173     ;MEM = Memory, 
174     ;MMIO = Memory Mapped IO, 
175     ;IO = in/out, 
176     ;PCI = PCI Config space
177     Default access type is memory (MEM)
178
179   For Shell Mode 1.1.2:
180     MM Address [Width] [-[MEM | MMIO | IO | PCI]] [:Value]
181     1|2|4|8 supported byte widths - Default is 1 byte. 
182     -MEM = Memory, 
183     -MMIO = Memory Mapped IO, 
184     -IO = in/out, 
185     -PCI = PCI Config space
186     Default access type is memory (MEM)
187
188 --*/
189 {
190   EFI_STATUS                      Status;
191   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
192   UINT64                          Address;
193   UINT64                          Value;
194   EFI_IO_WIDTH                    Width;
195   EFI_ACCESS_TYPE                 AccessType;
196   UINT64                          Buffer;
197   UINTN                           Index;
198   UINTN                           Size;
199   CHAR16                          *AddressStr;
200   CHAR16                          *ValueStr;
201   BOOLEAN                         Complete;
202   CHAR16                          InputStr[80];
203   BOOLEAN                         Interactive;
204
205   SHELL_VAR_CHECK_CODE            RetCode;
206   CHAR16                          *Useful;
207   SHELL_ARG_LIST                  *Item;
208   UINTN                           ItemValue;
209   SHELL_VAR_CHECK_PACKAGE         ChkPck;
210
211   Address = 0;
212   IoDev = NULL;
213   ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE));
214
215   EFI_SHELL_APP_INIT (ImageHandle, SystemTable);
216
217   Status = LibInitializeStrings (&HiiHandle, STRING_ARRAY_NAME, &EfiIomodGuid);
218
219   if (EFI_ERROR (Status)) {
220     return Status;
221   }
222
223   if (!EFI_PROPER_VERSION (1, 10)) {
224     PrintToken (
225       STRING_TOKEN (STR_SHELLENV_GNC_COMMAND_NOT_SUPPORT),
226       HiiHandle,
227       L"mm",
228       EFI_VERSION_1_10
229       );
230     Status = EFI_UNSUPPORTED;
231     goto Done;
232   }
233
234   if (IS_OLD_SHELL) {
235     Status = OldShellParserMM (&Width, &AccessType, &Address, &Value, &Size, &Interactive, &ValueStr);
236     if (EFI_ERROR (Status)) {
237       if (-1 == Status) {
238         PrintToken (STRING_TOKEN (STR_HELPINFO_MM_VERBOSEHELP), HiiHandle);
239         Status = EFI_SUCCESS;
240       }
241       goto Done;
242     }
243   } else {
244     //
245     // Parse arguments
246     //
247     Width       = EfiPciWidthUint8;
248     Size        = 1;
249     AccessType  = EfiMemory;
250     AddressStr  = NULL;
251     ValueStr    = NULL;
252     Interactive = TRUE;
253
254     RetCode     = LibCheckVariables (SI, IomodCheckList, &ChkPck, &Useful);
255     if (VarCheckOk != RetCode) {
256       switch (RetCode) {
257       case VarCheckUnknown:
258         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"mm", Useful);
259         break;
260
261       case VarCheckConflict:
262         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"mm", Useful);
263         break;
264
265       case VarCheckDuplicate:
266         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"mm", Useful);
267         break;
268
269       case VarCheckLackValue:
270         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_LACK_ARG), HiiHandle, L"mm", Useful);
271         break;
272
273       default:
274         break;
275       }
276
277       Status = EFI_INVALID_PARAMETER;
278       goto Done;
279     }
280     //
281     // Out put help.
282     //
283     if (LibCheckVarGetFlag (&ChkPck, L"-b") != NULL) {
284       EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
285     }
286
287     if (LibCheckVarGetFlag (&ChkPck, L"-?") != NULL) {
288       if (ChkPck.ValueCount > 0 ||
289           ChkPck.FlagCount > 2 ||
290           (2 == ChkPck.FlagCount && !LibCheckVarGetFlag (&ChkPck, L"-b"))
291           ) {
292         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"mv");
293         Status = EFI_INVALID_PARAMETER;
294       } else {
295         PrintToken (STRING_TOKEN (STR_HELPINFO_MM_VERBOSEHELP), HiiHandle);
296         Status = EFI_SUCCESS;
297       }
298       goto Done;
299     }
300
301     if (ChkPck.ValueCount < 1) {
302       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_FEW), HiiHandle, L"mm");
303       Status = EFI_INVALID_PARAMETER;
304       goto Done;
305     }
306
307     if (ChkPck.ValueCount > 2) {
308       PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"mm");
309       Status = EFI_INVALID_PARAMETER;
310       goto Done;
311     }
312
313     if (LibCheckVarGetFlag (&ChkPck, L"-MMIO") != NULL) {
314       AccessType = EFIMemoryMappedIo;
315     } else if (LibCheckVarGetFlag (&ChkPck, L"-MEM") != NULL) {
316       AccessType = EfiMemory;
317     } else if (LibCheckVarGetFlag (&ChkPck, L"-IO") != NULL) {
318       AccessType = EfiIo;
319     } else if (LibCheckVarGetFlag (&ChkPck, L"-PCI") != NULL) {
320       AccessType = EfiPciConfig;
321     }
322
323     if (LibCheckVarGetFlag (&ChkPck, L"-n") != NULL) {
324       Interactive = FALSE;
325     }
326
327     Item = LibCheckVarGetFlag (&ChkPck, L"-w");
328     if (NULL != Item) {
329       ItemValue = (UINTN) StrToUInteger (Item->VarStr, &Status);
330       if (EFI_ERROR (Status)) {
331         PrintToken (STRING_TOKEN (STR_IOMOD_INVALID_WIDTH), HiiHandle, L"mm");
332         Status = EFI_INVALID_PARAMETER;
333         goto Done;
334       }
335
336       switch (ItemValue) {
337       case 1:
338         Width = EfiPciWidthUint8;
339         Size  = 1;
340         break;
341
342       case 2:
343         Width = EfiPciWidthUint16;
344         Size  = 2;
345         break;
346
347       case 4:
348         Width = EfiPciWidthUint32;
349         Size  = 4;
350         break;
351
352       case 8:
353         Width = EfiPciWidthUint64;
354         Size  = 8;
355         break;
356
357       default:
358         PrintToken (STRING_TOKEN (STR_IOMOD_INVALID_WIDTH), HiiHandle, L"mm");
359         Status = EFI_INVALID_PARAMETER;
360         goto Done;
361       }
362     }
363
364     Item = ChkPck.VarList;
365     if (NULL != Item) {
366       Address = (UINT64) (StrToUIntegerBase (Item->VarStr, 16, &Status));
367       if (EFI_ERROR (Status)) {
368         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"mm", Item->VarStr);
369         Status = EFI_INVALID_PARAMETER;
370         goto Done;
371       }
372
373       Item = Item->Next;
374     }
375
376     if (NULL != Item) {
377       Value = (UINT64) (StrToUIntegerBase (Item->VarStr, 16, &Status));
378       if (EFI_ERROR (Status)) {
379         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"mm", Item->VarStr);
380         Status = EFI_INVALID_PARAMETER;
381         goto Done;
382       } else {
383         switch (Size) {
384         case 1:
385           if (Value > 0xFF) {
386             Status = EFI_INVALID_PARAMETER;
387           }
388           break;
389
390         case 2:
391           if (Value > 0xFFFF) {
392             Status = EFI_INVALID_PARAMETER;
393           }
394           break;
395
396         case 4:
397           if (Value > 0xFFFFFFFF) {
398             Status = EFI_INVALID_PARAMETER;
399           }
400           break;
401
402         default:
403           break;
404         }
405       }
406
407       if (EFI_ERROR (Status)) {
408         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"mm", Item->VarStr);
409         Status = EFI_INVALID_PARAMETER;
410         goto Done;
411       }
412
413       ValueStr = Item->VarStr;
414     }
415   }
416
417   if ((Address & (Size - 1)) != 0) {
418     PrintToken (STRING_TOKEN (STR_IOMOD_ADDRESS_NOT_ALIGNED), HiiHandle, L"mm", (UINTN) Address, Size);
419     Status = EFI_INVALID_PARAMETER;
420     goto Done;
421   }
422   //
423   // locate DeviceIO protocol interface
424   //
425   if (AccessType != EfiMemory) {
426     Status = BS->LocateProtocol (
427                   &gEfiPciRootBridgeIoProtocolGuid,
428                   NULL,
429                   (VOID *) &IoDev
430                   );
431     if (EFI_ERROR (Status)) {
432       PrintToken (STRING_TOKEN (STR_IOMOD_HANDLE_PCI), HiiHandle, L"mm", Status);
433       goto Done;
434     }
435   }
436
437   if (AccessType == EfiIo && Address + Size > 0x10000) {
438     PrintToken (STRING_TOKEN (STR_IOMOD_IO_ADDRESS), HiiHandle, L"mm");
439     Status = EFI_INVALID_PARAMETER;
440     goto Done;
441   }
442   //
443   // Set value
444   //
445   if (ValueStr) {
446     if (AccessType == EFIMemoryMappedIo) {
447       IoDev->Mem.Write (IoDev, Width, Address, 1, &Value);
448     } else if (AccessType == EfiIo) {
449       IoDev->Io.Write (IoDev, Width, Address, 1, &Value);
450     } else if (AccessType == EfiPciConfig) {
451       IoDev->Pci.Write (IoDev, Width, Address, 1, &Value);
452     } else {
453       WriteMem (Width, Address, 1, &Value);
454     }
455
456     Status = EFI_SUCCESS;
457     goto Done;
458   }
459   //
460   // non-interactive mode
461   //
462   if (Interactive == FALSE) {
463     Buffer = 0;
464     if (AccessType == EFIMemoryMappedIo) {
465       PrintToken (STRING_TOKEN (STR_IOMOD_HMMIO), HiiHandle);
466       IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
467     } else if (AccessType == EfiIo) {
468       PrintToken (STRING_TOKEN (STR_IOMOD_HIO), HiiHandle);
469       IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
470     } else if (AccessType == EfiPciConfig) {
471       PrintToken (STRING_TOKEN (STR_IOMOD_HPCI), HiiHandle);
472       IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
473     } else {
474       PrintToken (STRING_TOKEN (STR_IOMOD_HMEM), HiiHandle);
475       ReadMem (Width, Address, 1, &Buffer);
476     }
477
478     PrintToken (STRING_TOKEN (STR_IOMOD_ADDRESS), HiiHandle, Address);
479     if (Size == 1) {
480       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_2), HiiHandle, Buffer);
481     } else if (Size == 2) {
482       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_4), HiiHandle, Buffer);
483     } else if (Size == 4) {
484       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_8), HiiHandle, Buffer);
485     } else if (Size == 8) {
486       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_16), HiiHandle, Buffer);
487     }
488
489     Print (L"\n");
490     Status = EFI_SUCCESS;
491     goto Done;
492   }
493   //
494   // interactive mode
495   //
496   Complete = FALSE;
497   do {
498     if (AccessType == EfiIo && Address + Size > 0x10000) {
499       PrintToken (STRING_TOKEN (STR_IOMOD_IO_ADDRESS_2), HiiHandle, L"mm");
500       break;
501     }
502
503     Buffer = 0;
504     if (AccessType == EFIMemoryMappedIo) {
505       PrintToken (STRING_TOKEN (STR_IOMOD_HMMIO), HiiHandle);
506       IoDev->Mem.Read (IoDev, Width, Address, 1, &Buffer);
507     } else if (AccessType == EfiIo) {
508       PrintToken (STRING_TOKEN (STR_IOMOD_HIO), HiiHandle);
509       IoDev->Io.Read (IoDev, Width, Address, 1, &Buffer);
510     } else if (AccessType == EfiPciConfig) {
511       PrintToken (STRING_TOKEN (STR_IOMOD_HPCI), HiiHandle);
512       IoDev->Pci.Read (IoDev, Width, Address, 1, &Buffer);
513     } else {
514       PrintToken (STRING_TOKEN (STR_IOMOD_HMEM), HiiHandle);
515       ReadMem (Width, Address, 1, &Buffer);
516     }
517
518     PrintToken (STRING_TOKEN (STR_IOMOD_ADDRESS), HiiHandle, Address);
519
520     if (Size == 1) {
521       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_2), HiiHandle, Buffer);
522     } else if (Size == 2) {
523       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_4), HiiHandle, Buffer);
524     } else if (Size == 4) {
525       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_8), HiiHandle, Buffer);
526     } else if (Size == 8) {
527       PrintToken (STRING_TOKEN (STR_IOMOD_BUFFER_16), HiiHandle, Buffer);
528     }
529     //
530     // wait user input to modify
531     //
532     Input (L" > ", InputStr, sizeof (InputStr) / sizeof (CHAR16));
533
534     //
535     // skip space characters
536     //
537     for (Index = 0; InputStr[Index] == ' '; Index++)
538       ;
539
540     //
541     // parse input string
542     //
543     if (InputStr[Index] == '.' || InputStr[Index] == 'q' || InputStr[Index] == 'Q') {
544       Complete = TRUE;
545     } else if (InputStr[Index] == CHAR_NULL) {
546       //
547       // Continue to next address
548       //
549     } else if (GetHex (InputStr + Index, &Buffer) && Buffer <= MaxNum[Width]) {
550       if (AccessType == EFIMemoryMappedIo) {
551         IoDev->Mem.Write (IoDev, Width, Address, 1, &Buffer);
552       } else if (AccessType == EfiIo) {
553         IoDev->Io.Write (IoDev, Width, Address, 1, &Buffer);
554       } else if (AccessType == EfiPciConfig) {
555         IoDev->Pci.Write (IoDev, Width, Address, 1, &Buffer);
556       } else {
557         WriteMem (Width, Address, 1, &Buffer);
558       }
559     } else {
560       PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
561       continue;
562     }
563
564     Address += Size;
565     Print (L"\n");
566   } while (!Complete);
567
568   Status = EFI_SUCCESS;
569 Done:
570
571   LibCheckVarFreeVarList (&ChkPck);
572   LibUnInitializeStrings ();
573   return Status;
574 }
575
576 VOID
577 ReadMem (
578   IN  EFI_IO_WIDTH  Width,
579   IN  UINT64        Address,
580   IN  UINTN         Size,
581   IN  VOID          *Buffer
582   )
583 {
584   do {
585     if (Width == EfiPciWidthUint8) {
586       *(UINT8 *) Buffer = *(UINT8 *) (UINTN) Address;
587       Address -= 1;
588     } else if (Width == EfiPciWidthUint16) {
589       *(UINT16 *) Buffer = *(UINT16 *) (UINTN) Address;
590       Address -= 2;
591     } else if (Width == EfiPciWidthUint32) {
592       *(UINT32 *) Buffer = *(UINT32 *) (UINTN) Address;
593       Address -= 4;
594     } else if (Width == EfiPciWidthUint64) {
595       *(UINT64 *) Buffer = *(UINT64 *) (UINTN) Address;
596       Address -= 8;
597     } else {
598       PrintToken (STRING_TOKEN (STR_IOMOD_READ_MEM_ERROR), HiiHandle);
599       break;
600     }
601     //
602     //
603     //
604     Size--;
605   } while (Size > 0);
606 }
607
608 VOID
609 WriteMem (
610   IN  EFI_IO_WIDTH  Width,
611   IN  UINT64        Address,
612   IN  UINTN         Size,
613   IN  VOID          *Buffer
614   )
615 {
616   do {
617     if (Width == EfiPciWidthUint8) {
618       *(UINT8 *) (UINTN) Address = *(UINT8 *) Buffer;
619       Address += 1;
620     } else if (Width == EfiPciWidthUint16) {
621       *(UINT16 *) (UINTN) Address = *(UINT16 *) Buffer;
622       Address += 2;
623     } else if (Width == EfiPciWidthUint32) {
624       *(UINT32 *) (UINTN) Address = *(UINT32 *) Buffer;
625       Address += 4;
626     } else if (Width == EfiPciWidthUint64) {
627       *(UINT64 *) (UINTN) Address = *(UINT64 *) Buffer;
628       Address += 8;
629     } else {
630       ASSERT (FALSE);
631     }
632     //
633     //
634     //
635     Size--;
636   } while (Size > 0);
637 }
638
639 STATIC
640 BOOLEAN
641 GetHex (
642   IN  UINT16  *str,
643   OUT UINT64  *data
644   )
645 {
646   UINTN   u;
647   CHAR16  c;
648   BOOLEAN Find;
649
650   Find = FALSE;
651   //
652   // convert hex digits
653   //
654   u = 0;
655   c = *(str++);
656   while (c) {
657     if (c >= 'a' && c <= 'f') {
658       c -= 'a' - 'A';
659     }
660
661     if (c == ' ') {
662       break;
663     }
664
665     if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
666       u     = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0');
667
668       Find  = TRUE;
669     } else {
670       return FALSE;
671     }
672
673     c = *(str++);
674   }
675
676   *data = u;
677   return Find;
678 }
679
680 EFI_STATUS
681 OldShellParserMM (
682   OUT EFI_IO_WIDTH       *Width,
683   OUT EFI_ACCESS_TYPE    *AccessType,
684   OUT UINT64             *Address,
685   OUT UINT64             *Value,
686   OUT UINTN              *Size,
687   OUT BOOLEAN            *Interactive,
688   OUT CHAR16             **ValueStr
689   )
690 /*++
691
692 Routine Description:
693
694   Parse the command line with old shell command grammar
695
696 Arguments:
697
698   Width              - The memory width
699   AccessType         - The memory access type
700   Address            - The memory address
701   Value              - The memory value
702   Size               - The memory size
703   Interactive        - Interactive
704   ValueStr           - The value string
705
706 Returns:
707
708   EFI_SUCCESS   - Success
709
710 --*/
711 {
712   CHAR16  *AddressStr;
713   CHAR16  *WidthStr;
714   CHAR16  *Ptr;
715   UINTN   Index;
716   BOOLEAN PrtHelp;
717   //
718   // Parse arguments
719   //
720   *Width                = EfiPciWidthUint8;
721   *Size                 = 1;
722   *AccessType           = EfiMemory;
723   AddressStr            = WidthStr = NULL;
724   *ValueStr             = NULL;
725   *Interactive          = TRUE;
726   PrtHelp               = FALSE;
727   for (Index = 1; Index < SI->Argc; Index += 1) {
728     Ptr = SI->Argv[Index];
729     //
730     // access type
731     //
732     if (*Ptr == L';') {
733       if (StriCmp (Ptr, L";IO") == 0) {
734         *AccessType = EfiIo;
735         continue;
736       } else if (StriCmp (Ptr, L";PCI") == 0) {
737         *AccessType = EfiPciConfig;
738         continue;
739       } else if (StriCmp (Ptr, L";MEM") == 0) {
740         *AccessType = EfiMemory;
741         continue;
742       } else if (StriCmp (Ptr, L";MMIO") == 0) {
743         *AccessType = EFIMemoryMappedIo;
744         continue;
745       } else {
746         PrintToken (STRING_TOKEN (STR_IOMOD_UNKNOWN_ACCESS), HiiHandle, L"mm", Ptr);
747         return EFI_INVALID_PARAMETER;
748       }
749     } else if (*Ptr == ':') {
750       //
751       // value
752       //
753       *ValueStr = &Ptr[1];
754       *Value    = Xtoi (*ValueStr);
755       continue;
756     } else if (*Ptr == '-') {
757       //
758       // command option switch
759       //
760       switch (Ptr[1]) {
761       case 'n':
762       case 'N':
763         *Interactive = FALSE;
764         break;
765
766       case '?':
767         PrtHelp = TRUE;
768         break;
769
770       case 'b':
771       case 'B':
772         EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
773         break;
774
775       default:
776         PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"mm", Ptr);
777         return EFI_INVALID_PARAMETER;
778       };
779       continue;
780     }
781
782     //
783     // Start Address
784     //
785     if (!AddressStr) {
786       AddressStr  = Ptr;
787       *Address    = Xtoi (AddressStr);
788       continue;
789     }
790     //
791     // access width
792     //
793     if (!WidthStr) {
794       WidthStr = Ptr;
795       switch (Xtoi (WidthStr)) {
796       case 1:
797         *Width  = EfiPciWidthUint8;
798         *Size   = 1;
799         continue;
800
801       case 2:
802         *Width  = EfiPciWidthUint16;
803         *Size   = 2;
804         continue;
805
806       case 4:
807         *Width  = EfiPciWidthUint32;
808         *Size   = 4;
809         continue;
810
811       case 8:
812         *Width  = EfiPciWidthUint64;
813         *Size   = 8;
814         continue;
815
816       default:
817         PrintToken (STRING_TOKEN (STR_IOMOD_INVALID_WIDTH), HiiHandle, L"mm");
818         return EFI_INVALID_PARAMETER;
819       }
820     }
821   }
822
823   if (PrtHelp) {
824     return (EFI_STATUS) -1;
825   }
826
827   return EFI_SUCCESS;
828 }
829
830 EFI_STATUS
831 InitializeMMGetLineHelp (
832   OUT CHAR16              **Str
833   )
834 /*++
835
836 Routine Description:
837
838   Get this command's line help
839
840 Arguments:
841
842   Str - The line help
843
844 Returns:
845
846   EFI_SUCCESS   - Success
847
848 --*/
849 {
850   return LibCmdGetStringByToken (
851           STRING_ARRAY_NAME,
852           &EfiIomodGuid,
853           STRING_TOKEN (STR_HELPINFO_MM_LINEHELP),
854           Str
855           );
856 }