]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
ShellPkg/[hex]edit: use SimpleTextInEx to read console
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Mm.c
CommitLineData
5d73d92f 1/** @file\r
2 Main file for Mm shell Debug1 function.\r
3\r
c011b6c9 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
0027921b 5 Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>\r
5d73d92f 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "UefiShellDebug1CommandsLib.h"\r
17#include <Library/ShellLib.h>\r
304316f4 18#include <Library/IoLib.h>\r
5d73d92f 19#include <Protocol/PciRootBridgeIo.h>\r
20#include <Protocol/DeviceIo.h>\r
21\r
22typedef enum {\r
304316f4
RN
23 ShellMmMemory,\r
24 ShellMmMemoryMappedIo,\r
25 ShellMmIo,\r
26 ShellMmPci,\r
27 ShellMmPciExpress\r
28} SHELL_MM_ACCESS_TYPE;\r
29\r
30CONST UINT16 mShellMmAccessTypeStr[] = {\r
31 STRING_TOKEN (STR_MM_MEM),\r
32 STRING_TOKEN (STR_MM_MMIO),\r
33 STRING_TOKEN (STR_MM_IO),\r
34 STRING_TOKEN (STR_MM_PCI),\r
35 STRING_TOKEN (STR_MM_PCIE)\r
36};\r
5d73d92f 37\r
3737ac2b 38STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
39 {L"-mmio", TypeFlag},\r
40 {L"-mem", TypeFlag},\r
41 {L"-io", TypeFlag},\r
42 {L"-pci", TypeFlag},\r
43 {L"-pcie", TypeFlag},\r
44 {L"-n", TypeFlag},\r
45 {L"-w", TypeValue},\r
46 {NULL, TypeMax}\r
47 };\r
48\r
304316f4
RN
49CONST UINT64 mShellMmMaxNumber[] = {\r
50 0, MAX_UINT8, MAX_UINT16, 0, MAX_UINT32, 0, 0, 0, MAX_UINT64\r
51};\r
52CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth[] = {\r
53 0, EfiPciWidthUint8, EfiPciWidthUint16, 0, EfiPciWidthUint32, 0, 0, 0, EfiPciWidthUint64\r
54};\r
55CONST EFI_CPU_IO_PROTOCOL_WIDTH mShellMmCpuIoWidth[] = {\r
56 0, EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, 0, EfiCpuIoWidthUint32, 0, 0, 0, EfiCpuIoWidthUint64\r
57};\r
3737ac2b 58\r
59/**\r
304316f4 60 Extract the PCI segment, bus, device, function, register from\r
0027921b 61 from a PCI or PCIE format of address..\r
304316f4
RN
62\r
63 @param[in] PciFormat Whether the address is of PCI format of PCIE format.\r
0027921b 64 @param[in] Address PCI or PCIE address.\r
304316f4
RN
65 @param[out] Segment PCI segment number.\r
66 @param[out] Bus PCI bus number.\r
67 @param[out] Device PCI device number.\r
68 @param[out] Function PCI function number.\r
69 @param[out] Register PCI register offset.\r
3737ac2b 70**/\r
5d73d92f 71VOID\r
304316f4
RN
72ShellMmDecodePciAddress (\r
73 IN BOOLEAN PciFormat,\r
74 IN UINT64 Address,\r
75 OUT UINT32 *Segment,\r
76 OUT UINT8 *Bus,\r
77 OUT UINT8 *Device, OPTIONAL\r
78 OUT UINT8 *Function, OPTIONAL\r
79 OUT UINT32 *Register OPTIONAL\r
3737ac2b 80 )\r
81{\r
304316f4
RN
82 if (PciFormat) {\r
83 //\r
0027921b
RN
84 // PCI Configuration Space.The address will have the format ssssbbddffrr,\r
85 // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register.\r
304316f4 86 //\r
0027921b 87 *Segment = (UINT32) (RShiftU64 (Address, 32) & 0xFFFF);\r
304316f4
RN
88 *Bus = (UINT8) (((UINT32) Address) >> 24);\r
89\r
90 if (Device != NULL) {\r
91 *Device = (UINT8) (((UINT32) Address) >> 16);\r
92 }\r
93 if (Function != NULL) {\r
94 *Function = (UINT8) (((UINT32) Address) >> 8);\r
3737ac2b 95 }\r
304316f4
RN
96 if (Register != NULL) {\r
97 *Register = (UINT8) Address;\r
98 }\r
99 } else {\r
100 //\r
0027921b
RN
101 // PCI Express Configuration Space.The address will have the format ssssssbbddffrrr,\r
102 // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register.\r
304316f4 103 //\r
0027921b 104 *Segment = (UINT32) (RShiftU64 (Address, 36) & 0xFFFF);\r
304316f4
RN
105 *Bus = (UINT8) RShiftU64 (Address, 28);\r
106 if (Device != NULL) {\r
107 *Device = (UINT8) (((UINT32) Address) >> 20);\r
108 }\r
109 if (Function != NULL) {\r
110 *Function = (UINT8) (((UINT32) Address) >> 12);\r
111 }\r
112 if (Register != NULL) {\r
113 *Register = (UINT32) (Address & 0xFFF);\r
114 }\r
115 }\r
3737ac2b 116}\r
117\r
118/**\r
304316f4
RN
119 Read or write some data from or into the Address.\r
120\r
121 @param[in] AccessType Access type.\r
122 @param[in] PciRootBridgeIo PciRootBridgeIo instance.\r
123 @param[in] CpuIo CpuIo instance.\r
124 @param[in] Read TRUE for read, FALSE for write.\r
125 @param[in] Addresss The memory location to access.\r
126 @param[in] Size The size of Buffer in Width sized units.\r
127 @param[in, out] Buffer The buffer to read into or write from.\r
3737ac2b 128**/\r
5d73d92f 129VOID\r
304316f4
RN
130ShellMmAccess (\r
131 IN SHELL_MM_ACCESS_TYPE AccessType,\r
132 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,\r
133 IN EFI_CPU_IO2_PROTOCOL *CpuIo,\r
134 IN BOOLEAN Read,\r
135 IN UINT64 Address,\r
136 IN UINTN Size,\r
137 IN OUT VOID *Buffer\r
3737ac2b 138 )\r
139{\r
304316f4
RN
140 EFI_STATUS Status;\r
141 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM RootBridgeIoMem;\r
142 EFI_CPU_IO_PROTOCOL_IO_MEM CpuIoMem;\r
143 UINT32 Segment;\r
144 UINT8 Bus;\r
145 UINT8 Device;\r
146 UINT8 Function;\r
147 UINT32 Register;\r
148\r
149 if (AccessType == ShellMmMemory) {\r
150 if (Read) {\r
151 CopyMem (Buffer, (VOID *) (UINTN) Address, Size);\r
3737ac2b 152 } else {\r
304316f4
RN
153 CopyMem ((VOID *) (UINTN) Address, Buffer, Size);\r
154 }\r
155 } else {\r
156 RootBridgeIoMem = NULL;\r
157 CpuIoMem = NULL;\r
158 switch (AccessType) {\r
159 case ShellMmPci:\r
160 case ShellMmPciExpress:\r
161 ASSERT (PciRootBridgeIo != NULL);\r
162 ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, &Device, &Function, &Register);\r
163 if (Read) {\r
164 Status = PciRootBridgeIo->Pci.Read (\r
165 PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size],\r
166 EFI_PCI_ADDRESS (Bus, Device, Function, Register),\r
167 1, Buffer\r
168 );\r
169 } else {\r
170 Status = PciRootBridgeIo->Pci.Write (\r
171 PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size],\r
172 EFI_PCI_ADDRESS (Bus, Device, Function, Register),\r
173 1, Buffer\r
174 );\r
175 }\r
176 ASSERT_EFI_ERROR (Status);\r
177 return;\r
178\r
179 case ShellMmMemoryMappedIo:\r
180 if (PciRootBridgeIo != NULL) {\r
181 RootBridgeIoMem = Read ? PciRootBridgeIo->Mem.Read : PciRootBridgeIo->Mem.Write;\r
182 }\r
183 if (CpuIo != NULL) {\r
184 CpuIoMem = Read ? CpuIo->Mem.Read : CpuIo->Mem.Write;\r
185 }\r
186 break;\r
187\r
188 case ShellMmIo:\r
189 if (PciRootBridgeIo != NULL) {\r
190 RootBridgeIoMem = Read ? PciRootBridgeIo->Io.Read : PciRootBridgeIo->Io.Write;\r
191 }\r
192 if (CpuIo != NULL) {\r
193 CpuIoMem = Read ? CpuIo->Io.Read : CpuIo->Io.Write;\r
194 }\r
195 break;\r
196 default:\r
3737ac2b 197 ASSERT (FALSE);\r
304316f4 198 break;\r
3737ac2b 199 }\r
304316f4
RN
200\r
201 Status = EFI_UNSUPPORTED;\r
202 if (RootBridgeIoMem != NULL) {\r
203 Status = RootBridgeIoMem (PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], Address, 1, Buffer);\r
204 }\r
205 if (EFI_ERROR (Status) && (CpuIoMem != NULL)) {\r
206 Status = CpuIoMem (CpuIo, mShellMmCpuIoWidth[Size], Address, 1, Buffer);\r
207 }\r
208\r
209 if (EFI_ERROR (Status)) {\r
210 if (AccessType == ShellMmIo) {\r
211 switch (Size) {\r
212 case 1:\r
213 if (Read) {\r
214 *(UINT8 *) Buffer = IoRead8 ((UINTN) Address);\r
215 } else {\r
216 IoWrite8 ((UINTN) Address, *(UINT8 *) Buffer);\r
217 }\r
218 break;\r
219 case 2:\r
220 if (Read) {\r
221 *(UINT16 *) Buffer = IoRead16 ((UINTN) Address);\r
222 } else {\r
223 IoWrite16 ((UINTN) Address, *(UINT16 *) Buffer);\r
224 }\r
225 break;\r
226 case 4:\r
227 if (Read) {\r
228 *(UINT32 *) Buffer = IoRead32 ((UINTN) Address);\r
229 } else {\r
230 IoWrite32 ((UINTN) Address, *(UINT32 *) Buffer);\r
231 }\r
232 break;\r
233 case 8:\r
234 if (Read) {\r
235 *(UINT64 *) Buffer = IoRead64 ((UINTN) Address);\r
236 } else {\r
237 IoWrite64 ((UINTN) Address, *(UINT64 *) Buffer);\r
238 }\r
239 break;\r
240 default:\r
241 ASSERT (FALSE);\r
242 break;\r
243 }\r
244 } else {\r
245 switch (Size) {\r
246 case 1:\r
247 if (Read) {\r
248 *(UINT8 *) Buffer = MmioRead8 ((UINTN) Address);\r
249 } else {\r
250 MmioWrite8 ((UINTN) Address, *(UINT8 *) Buffer);\r
251 }\r
252 break;\r
253 case 2:\r
254 if (Read) {\r
255 *(UINT16 *) Buffer = MmioRead16 ((UINTN) Address);\r
256 } else {\r
257 MmioWrite16 ((UINTN) Address, *(UINT16 *) Buffer);\r
258 }\r
259 break;\r
260 case 4:\r
261 if (Read) {\r
262 *(UINT32 *) Buffer = MmioRead32 ((UINTN) Address);\r
263 } else {\r
264 MmioWrite32 ((UINTN) Address, *(UINT32 *) Buffer);\r
265 }\r
266 break;\r
267 case 8:\r
268 if (Read) {\r
269 *(UINT64 *) Buffer = MmioRead64 ((UINTN) Address);\r
270 } else {\r
271 MmioWrite64 ((UINTN) Address, *(UINT64 *) Buffer);\r
272 }\r
273 break;\r
274 default:\r
275 ASSERT (FALSE);\r
276 break;\r
277 }\r
278 }\r
279 }\r
280 }\r
3737ac2b 281}\r
5d73d92f 282\r
3737ac2b 283/**\r
304316f4
RN
284 Find the CpuIo instance and PciRootBridgeIo instance in the platform.\r
285 If there are multiple PciRootBridgeIo instances, the instance which manages\r
286 the Address is returned.\r
3737ac2b 287\r
304316f4
RN
288 @param[in] AccessType Access type.\r
289 @param[in] Address Address to access.\r
290 @param[out] CpuIo Return the CpuIo instance.\r
291 @param[out] PciRootBridgeIo Return the proper PciRootBridgeIo instance.\r
3737ac2b 292\r
304316f4
RN
293 @retval TRUE There are PciRootBridgeIo instances in the platform.\r
294 @retval FALSE There isn't PciRootBridgeIo instance in the platform.\r
3737ac2b 295**/\r
5d73d92f 296BOOLEAN\r
304316f4
RN
297ShellMmLocateIoProtocol (\r
298 IN SHELL_MM_ACCESS_TYPE AccessType,\r
299 IN UINT64 Address,\r
300 OUT EFI_CPU_IO2_PROTOCOL **CpuIo,\r
301 OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **PciRootBridgeIo\r
3737ac2b 302 )\r
303{\r
304316f4
RN
304 EFI_STATUS Status;\r
305 UINTN Index;\r
306 UINTN HandleCount;\r
307 EFI_HANDLE *HandleBuffer;\r
308 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Io;\r
309 UINT32 Segment;\r
310 UINT8 Bus;\r
311 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
312\r
313 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) CpuIo);\r
314 if (EFI_ERROR (Status)) {\r
315 *CpuIo = NULL;\r
316 }\r
317\r
318 *PciRootBridgeIo = NULL;\r
02d34825 319 HandleBuffer = NULL;\r
304316f4
RN
320 Status = gBS->LocateHandleBuffer (\r
321 ByProtocol,\r
322 &gEfiPciRootBridgeIoProtocolGuid,\r
323 NULL,\r
324 &HandleCount,\r
325 &HandleBuffer\r
326 );\r
02d34825 327 if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {\r
304316f4
RN
328 return FALSE;\r
329 }\r
330\r
f87b742a
MK
331 Segment = 0;\r
332 Bus = 0;\r
304316f4
RN
333 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {\r
334 ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL);\r
335 }\r
5d73d92f 336\r
3737ac2b 337 //\r
304316f4 338 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number\r
3737ac2b 339 //\r
304316f4
RN
340 for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) {\r
341 Status = gBS->HandleProtocol (\r
342 HandleBuffer[Index],\r
343 &gEfiPciRootBridgeIoProtocolGuid,\r
344 (VOID *) &Io\r
345 );\r
346 if (EFI_ERROR (Status)) {\r
347 continue;\r
3737ac2b 348 }\r
349\r
304316f4
RN
350 if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) ||\r
351 ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo))\r
352 ) {\r
353 Status = Io->Configuration (Io, (VOID **) &Descriptors);\r
354 if (!EFI_ERROR (Status)) {\r
355 while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
356 //\r
357 // Compare the segment and bus range for PCI/PCIE access\r
358 //\r
359 if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) &&\r
360 ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) &&\r
361 ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax))\r
362 ) {\r
363 *PciRootBridgeIo = Io;\r
364 break;\r
365\r
366 //\r
367 // Compare the address range for MMIO/IO access\r
368 //\r
369 } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) ||\r
370 ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo))\r
371 ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax))\r
372 ) {\r
373 *PciRootBridgeIo = Io;\r
374 break;\r
375 }\r
376 Descriptors++;\r
377 }\r
378 }\r
3737ac2b 379 }\r
304316f4
RN
380 }\r
381 if (HandleBuffer != NULL) {\r
382 FreePool (HandleBuffer);\r
3737ac2b 383 }\r
384\r
304316f4 385 return TRUE;\r
5d73d92f 386}\r
387\r
388/**\r
389 Function for 'mm' command.\r
390\r
391 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
392 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
393**/\r
394SHELL_STATUS\r
395EFIAPI\r
396ShellCommandRunMm (\r
397 IN EFI_HANDLE ImageHandle,\r
398 IN EFI_SYSTEM_TABLE *SystemTable\r
399 )\r
400{\r
304316f4
RN
401 EFI_STATUS Status;\r
402 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
403 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
404 UINT64 Address;\r
405 UINT64 Value;\r
406 SHELL_MM_ACCESS_TYPE AccessType;\r
407 UINT64 Buffer;\r
408 UINTN Index;\r
409 UINTN Size;\r
410 BOOLEAN Complete;\r
411 CHAR16 *InputStr;\r
412 BOOLEAN Interactive;\r
413 LIST_ENTRY *Package;\r
414 CHAR16 *ProblemParam;\r
415 SHELL_STATUS ShellStatus;\r
416 CONST CHAR16 *Temp;\r
417 BOOLEAN HasPciRootBridgeIo;\r
418\r
419 Value = 0;\r
420 Address = 0;\r
421 ShellStatus = SHELL_SUCCESS;\r
422 InputStr = NULL;\r
423 Size = 1;\r
424 AccessType = ShellMmMemory;\r
5d73d92f 425\r
426 //\r
427 // Parse arguments\r
428 //\r
5d73d92f 429 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
304316f4 430 if (EFI_ERROR (Status)) {\r
5d73d92f 431 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
304316f4
RN
432 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);\r
433 FreePool (ProblemParam);\r
5d73d92f 434 ShellStatus = SHELL_INVALID_PARAMETER;\r
435 goto Done;\r
436 } else {\r
304316f4 437 ASSERT (FALSE);\r
5d73d92f 438 }\r
439 } else {\r
304316f4
RN
440 if (ShellCommandLineGetCount (Package) < 2) {\r
441 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 442 ShellStatus = SHELL_INVALID_PARAMETER;\r
443 goto Done;\r
304316f4
RN
444 } else if (ShellCommandLineGetCount (Package) > 3) {\r
445 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 446 ShellStatus = SHELL_INVALID_PARAMETER;\r
447 goto Done;\r
304316f4
RN
448 } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) {\r
449 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w");\r
3737ac2b 450 ShellStatus = SHELL_INVALID_PARAMETER;\r
451 goto Done;\r
5d73d92f 452 } else {\r
304316f4
RN
453 if (ShellCommandLineGetFlag (Package, L"-mmio")) {\r
454 AccessType = ShellMmMemoryMappedIo;\r
455 if (ShellCommandLineGetFlag (Package, L"-mem")\r
456 || ShellCommandLineGetFlag (Package, L"-io")\r
457 || ShellCommandLineGetFlag (Package, L"-pci")\r
458 || ShellCommandLineGetFlag (Package, L"-pcie")\r
459 ) {\r
460 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 461 ShellStatus = SHELL_INVALID_PARAMETER;\r
462 goto Done;\r
463 }\r
304316f4
RN
464 } else if (ShellCommandLineGetFlag (Package, L"-mem")) {\r
465 AccessType = ShellMmMemory;\r
466 if (ShellCommandLineGetFlag (Package, L"-io")\r
467 || ShellCommandLineGetFlag (Package, L"-pci")\r
468 || ShellCommandLineGetFlag (Package, L"-pcie")\r
469 ) {\r
470 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 471 ShellStatus = SHELL_INVALID_PARAMETER;\r
472 goto Done;\r
473 }\r
304316f4
RN
474 } else if (ShellCommandLineGetFlag (Package, L"-io")) {\r
475 AccessType = ShellMmIo;\r
476 if (ShellCommandLineGetFlag (Package, L"-pci")\r
477 || ShellCommandLineGetFlag (Package, L"-pcie")\r
478 ) {\r
479 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 480 ShellStatus = SHELL_INVALID_PARAMETER;\r
481 goto Done;\r
482 }\r
304316f4
RN
483 } else if (ShellCommandLineGetFlag (Package, L"-pci")) {\r
484 AccessType = ShellMmPci;\r
485 if (ShellCommandLineGetFlag (Package, L"-pcie")\r
486 ) {\r
487 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 488 ShellStatus = SHELL_INVALID_PARAMETER;\r
489 goto Done;\r
490 }\r
304316f4
RN
491 } else if (ShellCommandLineGetFlag (Package, L"-pcie")) {\r
492 AccessType = ShellMmPciExpress;\r
5d73d92f 493 }\r
494 }\r
495\r
f79868cd
JC
496 //\r
497 // Non interactive for a script file or for the specific parameter\r
498 //\r
304316f4
RN
499 Interactive = TRUE;\r
500 if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) {\r
5d73d92f 501 Interactive = FALSE;\r
502 }\r
503\r
304316f4 504 Temp = ShellCommandLineGetValue (Package, L"-w");\r
5d73d92f 505 if (Temp != NULL) {\r
304316f4 506 Size = ShellStrToUintn (Temp);\r
5d73d92f 507 }\r
304316f4
RN
508 if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) {\r
509 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w");\r
3737ac2b 510 ShellStatus = SHELL_INVALID_PARAMETER;\r
511 goto Done;\r
5d73d92f 512 }\r
513\r
304316f4
RN
514 Temp = ShellCommandLineGetRawValue (Package, 1);\r
515 Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE);\r
516 if (EFI_ERROR (Status)) {\r
517 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
518 ShellStatus = SHELL_INVALID_PARAMETER;\r
519 goto Done;\r
5d73d92f 520 }\r
521\r
522 if ((Address & (Size - 1)) != 0) {\r
304316f4
RN
523 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address);\r
524 ShellStatus = SHELL_INVALID_PARAMETER;\r
525 goto Done;\r
526 }\r
527\r
528 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {\r
529 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_IO_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 530 ShellStatus = SHELL_INVALID_PARAMETER;\r
531 goto Done;\r
532 }\r
304316f4 533\r
5d73d92f 534 //\r
304316f4 535 // locate IO protocol interface\r
5d73d92f 536 //\r
304316f4
RN
537 HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo);\r
538 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {\r
539 if (!HasPciRootBridgeIo) {\r
540 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 541 ShellStatus = SHELL_NOT_FOUND;\r
542 goto Done;\r
543 }\r
304316f4
RN
544 if (PciRootBridgeIo == NULL) {\r
545 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address);\r
5d73d92f 546 ShellStatus = SHELL_INVALID_PARAMETER;\r
547 goto Done;\r
548 }\r
549 }\r
550\r
a0cd353d 551 //\r
304316f4 552 // Mode 1: Directly set a value\r
a0cd353d 553 //\r
304316f4
RN
554 Temp = ShellCommandLineGetRawValue (Package, 2);\r
555 if (Temp != NULL) {\r
556 Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE);\r
557 if (EFI_ERROR (Status)) {\r
558 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
559 ShellStatus = SHELL_INVALID_PARAMETER;\r
560 goto Done;\r
561 }\r
562\r
563 if (Value > mShellMmMaxNumber[Size]) {\r
564 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
565 ShellStatus = SHELL_INVALID_PARAMETER;\r
566 goto Done;\r
a0cd353d 567 }\r
568\r
304316f4 569 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value);\r
a0cd353d 570 goto Done;\r
571 }\r
5d73d92f 572\r
5d73d92f 573 //\r
304316f4 574 // Mode 2: Directly show a value\r
5d73d92f 575 //\r
576 if (!Interactive) {\r
304316f4
RN
577 if (!gEfiShellProtocol->BatchIsActive ()) {\r
578 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
5d73d92f 579 }\r
304316f4 580 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
5d73d92f 581\r
304316f4
RN
582 if (!gEfiShellProtocol->BatchIsActive ()) {\r
583 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
584 }\r
585 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
586 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 587 goto Done;\r
588 }\r
304316f4 589\r
5d73d92f 590 //\r
304316f4 591 // Mode 3: Show or set values in interactive mode\r
5d73d92f 592 //\r
593 Complete = FALSE;\r
594 do {\r
304316f4
RN
595 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {\r
596 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 597 break;\r
598 }\r
599\r
304316f4
RN
600 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
601 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
602 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
603 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
604 ShellPrintEx (-1, -1, L" > ");\r
5d73d92f 605 //\r
606 // wait user input to modify\r
607 //\r
608 if (InputStr != NULL) {\r
304316f4 609 FreePool (InputStr);\r
3737ac2b 610 InputStr = NULL;\r
5d73d92f 611 }\r
304316f4 612 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr);\r
5d73d92f 613\r
304316f4 614 if (InputStr != NULL) {\r
5d73d92f 615 //\r
304316f4 616 // skip space characters\r
5d73d92f 617 //\r
304316f4 618 for (Index = 0; InputStr[Index] == ' '; Index++);\r
304316f4 619\r
f87b742a
MK
620 if (InputStr[Index] != CHAR_NULL) {\r
621 if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) {\r
622 Complete = TRUE;\r
623 } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) &&\r
624 (Buffer <= mShellMmMaxNumber[Size])\r
625 ) {\r
626 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer);\r
627 } else {\r
628 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");\r
629 continue;\r
630 }\r
5d73d92f 631 }\r
5d73d92f 632 }\r
633\r
634 Address += Size;\r
304316f4 635 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 636 } while (!Complete);\r
637 }\r
304316f4 638 ASSERT (ShellStatus == SHELL_SUCCESS);\r
5d73d92f 639\r
304316f4 640Done:\r
5d73d92f 641 if (InputStr != NULL) {\r
304316f4 642 FreePool (InputStr);\r
5d73d92f 643 }\r
644 if (Package != NULL) {\r
645 ShellCommandLineFreeVarList (Package);\r
646 }\r
647 return ShellStatus;\r
648}\r