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