]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
ShellPkg/UefiShellDebug1CommandsLib: remove I/O address limit from 'mm'
[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
5d73d92f 528 //\r
304316f4 529 // locate IO protocol interface\r
5d73d92f 530 //\r
304316f4
RN
531 HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo);\r
532 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {\r
533 if (!HasPciRootBridgeIo) {\r
534 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 535 ShellStatus = SHELL_NOT_FOUND;\r
536 goto Done;\r
537 }\r
304316f4
RN
538 if (PciRootBridgeIo == NULL) {\r
539 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address);\r
5d73d92f 540 ShellStatus = SHELL_INVALID_PARAMETER;\r
541 goto Done;\r
542 }\r
543 }\r
544\r
a0cd353d 545 //\r
304316f4 546 // Mode 1: Directly set a value\r
a0cd353d 547 //\r
304316f4
RN
548 Temp = ShellCommandLineGetRawValue (Package, 2);\r
549 if (Temp != NULL) {\r
550 Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE);\r
551 if (EFI_ERROR (Status)) {\r
552 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
553 ShellStatus = SHELL_INVALID_PARAMETER;\r
554 goto Done;\r
555 }\r
556\r
557 if (Value > mShellMmMaxNumber[Size]) {\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
a0cd353d 561 }\r
562\r
304316f4 563 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value);\r
a0cd353d 564 goto Done;\r
565 }\r
5d73d92f 566\r
5d73d92f 567 //\r
304316f4 568 // Mode 2: Directly show a value\r
5d73d92f 569 //\r
570 if (!Interactive) {\r
304316f4
RN
571 if (!gEfiShellProtocol->BatchIsActive ()) {\r
572 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
5d73d92f 573 }\r
304316f4 574 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
5d73d92f 575\r
304316f4
RN
576 if (!gEfiShellProtocol->BatchIsActive ()) {\r
577 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
578 }\r
579 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
580 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 581 goto Done;\r
582 }\r
304316f4 583\r
5d73d92f 584 //\r
304316f4 585 // Mode 3: Show or set values in interactive mode\r
5d73d92f 586 //\r
587 Complete = FALSE;\r
588 do {\r
304316f4
RN
589 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
590 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
591 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
592 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
593 ShellPrintEx (-1, -1, L" > ");\r
5d73d92f 594 //\r
595 // wait user input to modify\r
596 //\r
597 if (InputStr != NULL) {\r
304316f4 598 FreePool (InputStr);\r
3737ac2b 599 InputStr = NULL;\r
5d73d92f 600 }\r
304316f4 601 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr);\r
5d73d92f 602\r
304316f4 603 if (InputStr != NULL) {\r
5d73d92f 604 //\r
304316f4 605 // skip space characters\r
5d73d92f 606 //\r
304316f4 607 for (Index = 0; InputStr[Index] == ' '; Index++);\r
304316f4 608\r
f87b742a
MK
609 if (InputStr[Index] != CHAR_NULL) {\r
610 if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) {\r
611 Complete = TRUE;\r
612 } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) &&\r
613 (Buffer <= mShellMmMaxNumber[Size])\r
614 ) {\r
615 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer);\r
616 } else {\r
617 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");\r
618 continue;\r
619 }\r
5d73d92f 620 }\r
5d73d92f 621 }\r
622\r
623 Address += Size;\r
304316f4 624 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 625 } while (!Complete);\r
626 }\r
304316f4 627 ASSERT (ShellStatus == SHELL_SUCCESS);\r
5d73d92f 628\r
304316f4 629Done:\r
5d73d92f 630 if (InputStr != NULL) {\r
304316f4 631 FreePool (InputStr);\r
5d73d92f 632 }\r
633 if (Package != NULL) {\r
634 ShellCommandLineFreeVarList (Package);\r
635 }\r
636 return ShellStatus;\r
637}\r