]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
ShellPkg/mm: Fix mm to support multiple root bridge platform
[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
320 Status = gBS->LocateHandleBuffer (\r
321 ByProtocol,\r
322 &gEfiPciRootBridgeIoProtocolGuid,\r
323 NULL,\r
324 &HandleCount,\r
325 &HandleBuffer\r
326 );\r
327 if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
328 return FALSE;\r
329 }\r
330\r
331 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {\r
332 ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL);\r
333 }\r
5d73d92f 334\r
3737ac2b 335 //\r
304316f4 336 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number\r
3737ac2b 337 //\r
304316f4
RN
338 for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) {\r
339 Status = gBS->HandleProtocol (\r
340 HandleBuffer[Index],\r
341 &gEfiPciRootBridgeIoProtocolGuid,\r
342 (VOID *) &Io\r
343 );\r
344 if (EFI_ERROR (Status)) {\r
345 continue;\r
3737ac2b 346 }\r
347\r
304316f4
RN
348 if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) ||\r
349 ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo))\r
350 ) {\r
351 Status = Io->Configuration (Io, (VOID **) &Descriptors);\r
352 if (!EFI_ERROR (Status)) {\r
353 while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
354 //\r
355 // Compare the segment and bus range for PCI/PCIE access\r
356 //\r
357 if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) &&\r
358 ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) &&\r
359 ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax))\r
360 ) {\r
361 *PciRootBridgeIo = Io;\r
362 break;\r
363\r
364 //\r
365 // Compare the address range for MMIO/IO access\r
366 //\r
367 } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) ||\r
368 ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo))\r
369 ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax))\r
370 ) {\r
371 *PciRootBridgeIo = Io;\r
372 break;\r
373 }\r
374 Descriptors++;\r
375 }\r
376 }\r
3737ac2b 377 }\r
304316f4
RN
378 }\r
379 if (HandleBuffer != NULL) {\r
380 FreePool (HandleBuffer);\r
3737ac2b 381 }\r
382\r
304316f4 383 return TRUE;\r
5d73d92f 384}\r
385\r
386/**\r
387 Function for 'mm' command.\r
388\r
389 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
390 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
391**/\r
392SHELL_STATUS\r
393EFIAPI\r
394ShellCommandRunMm (\r
395 IN EFI_HANDLE ImageHandle,\r
396 IN EFI_SYSTEM_TABLE *SystemTable\r
397 )\r
398{\r
304316f4
RN
399 EFI_STATUS Status;\r
400 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
401 EFI_CPU_IO2_PROTOCOL *CpuIo;\r
402 UINT64 Address;\r
403 UINT64 Value;\r
404 SHELL_MM_ACCESS_TYPE AccessType;\r
405 UINT64 Buffer;\r
406 UINTN Index;\r
407 UINTN Size;\r
408 BOOLEAN Complete;\r
409 CHAR16 *InputStr;\r
410 BOOLEAN Interactive;\r
411 LIST_ENTRY *Package;\r
412 CHAR16 *ProblemParam;\r
413 SHELL_STATUS ShellStatus;\r
414 CONST CHAR16 *Temp;\r
415 BOOLEAN HasPciRootBridgeIo;\r
416\r
417 Value = 0;\r
418 Address = 0;\r
419 ShellStatus = SHELL_SUCCESS;\r
420 InputStr = NULL;\r
421 Size = 1;\r
422 AccessType = ShellMmMemory;\r
5d73d92f 423\r
424 //\r
425 // Parse arguments\r
426 //\r
5d73d92f 427 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
304316f4 428 if (EFI_ERROR (Status)) {\r
5d73d92f 429 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
304316f4
RN
430 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);\r
431 FreePool (ProblemParam);\r
5d73d92f 432 ShellStatus = SHELL_INVALID_PARAMETER;\r
433 goto Done;\r
434 } else {\r
304316f4 435 ASSERT (FALSE);\r
5d73d92f 436 }\r
437 } else {\r
304316f4
RN
438 if (ShellCommandLineGetCount (Package) < 2) {\r
439 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 440 ShellStatus = SHELL_INVALID_PARAMETER;\r
441 goto Done;\r
304316f4
RN
442 } else if (ShellCommandLineGetCount (Package) > 3) {\r
443 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 444 ShellStatus = SHELL_INVALID_PARAMETER;\r
445 goto Done;\r
304316f4
RN
446 } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) {\r
447 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w");\r
3737ac2b 448 ShellStatus = SHELL_INVALID_PARAMETER;\r
449 goto Done;\r
5d73d92f 450 } else {\r
304316f4
RN
451 if (ShellCommandLineGetFlag (Package, L"-mmio")) {\r
452 AccessType = ShellMmMemoryMappedIo;\r
453 if (ShellCommandLineGetFlag (Package, L"-mem")\r
454 || ShellCommandLineGetFlag (Package, L"-io")\r
455 || ShellCommandLineGetFlag (Package, L"-pci")\r
456 || ShellCommandLineGetFlag (Package, L"-pcie")\r
457 ) {\r
458 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 459 ShellStatus = SHELL_INVALID_PARAMETER;\r
460 goto Done;\r
461 }\r
304316f4
RN
462 } else if (ShellCommandLineGetFlag (Package, L"-mem")) {\r
463 AccessType = ShellMmMemory;\r
464 if (ShellCommandLineGetFlag (Package, L"-io")\r
465 || ShellCommandLineGetFlag (Package, L"-pci")\r
466 || ShellCommandLineGetFlag (Package, L"-pcie")\r
467 ) {\r
468 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 469 ShellStatus = SHELL_INVALID_PARAMETER;\r
470 goto Done;\r
471 }\r
304316f4
RN
472 } else if (ShellCommandLineGetFlag (Package, L"-io")) {\r
473 AccessType = ShellMmIo;\r
474 if (ShellCommandLineGetFlag (Package, L"-pci")\r
475 || ShellCommandLineGetFlag (Package, L"-pcie")\r
476 ) {\r
477 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 478 ShellStatus = SHELL_INVALID_PARAMETER;\r
479 goto Done;\r
480 }\r
304316f4
RN
481 } else if (ShellCommandLineGetFlag (Package, L"-pci")) {\r
482 AccessType = ShellMmPci;\r
483 if (ShellCommandLineGetFlag (Package, L"-pcie")\r
484 ) {\r
485 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
3737ac2b 486 ShellStatus = SHELL_INVALID_PARAMETER;\r
487 goto Done;\r
488 }\r
304316f4
RN
489 } else if (ShellCommandLineGetFlag (Package, L"-pcie")) {\r
490 AccessType = ShellMmPciExpress;\r
5d73d92f 491 }\r
492 }\r
493\r
f79868cd
JC
494 //\r
495 // Non interactive for a script file or for the specific parameter\r
496 //\r
304316f4
RN
497 Interactive = TRUE;\r
498 if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) {\r
5d73d92f 499 Interactive = FALSE;\r
500 }\r
501\r
304316f4 502 Temp = ShellCommandLineGetValue (Package, L"-w");\r
5d73d92f 503 if (Temp != NULL) {\r
304316f4 504 Size = ShellStrToUintn (Temp);\r
5d73d92f 505 }\r
304316f4
RN
506 if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) {\r
507 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w");\r
3737ac2b 508 ShellStatus = SHELL_INVALID_PARAMETER;\r
509 goto Done;\r
5d73d92f 510 }\r
511\r
304316f4
RN
512 Temp = ShellCommandLineGetRawValue (Package, 1);\r
513 Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE);\r
514 if (EFI_ERROR (Status)) {\r
515 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
516 ShellStatus = SHELL_INVALID_PARAMETER;\r
517 goto Done;\r
5d73d92f 518 }\r
519\r
520 if ((Address & (Size - 1)) != 0) {\r
304316f4
RN
521 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address);\r
522 ShellStatus = SHELL_INVALID_PARAMETER;\r
523 goto Done;\r
524 }\r
525\r
526 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {\r
527 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_IO_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 528 ShellStatus = SHELL_INVALID_PARAMETER;\r
529 goto Done;\r
530 }\r
304316f4 531\r
5d73d92f 532 //\r
304316f4 533 // locate IO protocol interface\r
5d73d92f 534 //\r
304316f4
RN
535 HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo);\r
536 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {\r
537 if (!HasPciRootBridgeIo) {\r
538 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 539 ShellStatus = SHELL_NOT_FOUND;\r
540 goto Done;\r
541 }\r
304316f4
RN
542 if (PciRootBridgeIo == NULL) {\r
543 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address);\r
5d73d92f 544 ShellStatus = SHELL_INVALID_PARAMETER;\r
545 goto Done;\r
546 }\r
547 }\r
548\r
a0cd353d 549 //\r
304316f4 550 // Mode 1: Directly set a value\r
a0cd353d 551 //\r
304316f4
RN
552 Temp = ShellCommandLineGetRawValue (Package, 2);\r
553 if (Temp != NULL) {\r
554 Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE);\r
555 if (EFI_ERROR (Status)) {\r
556 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
557 ShellStatus = SHELL_INVALID_PARAMETER;\r
558 goto Done;\r
559 }\r
560\r
561 if (Value > mShellMmMaxNumber[Size]) {\r
562 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);\r
563 ShellStatus = SHELL_INVALID_PARAMETER;\r
564 goto Done;\r
a0cd353d 565 }\r
566\r
304316f4 567 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value);\r
a0cd353d 568 goto Done;\r
569 }\r
5d73d92f 570\r
5d73d92f 571 //\r
304316f4 572 // Mode 2: Directly show a value\r
5d73d92f 573 //\r
574 if (!Interactive) {\r
304316f4
RN
575 if (!gEfiShellProtocol->BatchIsActive ()) {\r
576 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
5d73d92f 577 }\r
304316f4 578 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
5d73d92f 579\r
304316f4
RN
580 if (!gEfiShellProtocol->BatchIsActive ()) {\r
581 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
582 }\r
583 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
584 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 585 goto Done;\r
586 }\r
304316f4 587\r
5d73d92f 588 //\r
304316f4 589 // Mode 3: Show or set values in interactive mode\r
5d73d92f 590 //\r
591 Complete = FALSE;\r
592 do {\r
304316f4
RN
593 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {\r
594 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm");\r
5d73d92f 595 break;\r
596 }\r
597\r
304316f4
RN
598 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
599 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
600 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);\r
601 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);\r
602 ShellPrintEx (-1, -1, L" > ");\r
5d73d92f 603 //\r
604 // wait user input to modify\r
605 //\r
606 if (InputStr != NULL) {\r
304316f4 607 FreePool (InputStr);\r
3737ac2b 608 InputStr = NULL;\r
5d73d92f 609 }\r
304316f4 610 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr);\r
5d73d92f 611\r
304316f4 612 if (InputStr != NULL) {\r
5d73d92f 613 //\r
304316f4 614 // skip space characters\r
5d73d92f 615 //\r
304316f4
RN
616 for (Index = 0; InputStr[Index] == ' '; Index++);\r
617 }\r
618\r
619 if ((InputStr != NULL) && (InputStr[Index] != CHAR_NULL)) {\r
620 if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) {\r
621 Complete = TRUE;\r
622 } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) &&\r
623 (Buffer <= mShellMmMaxNumber[Size])\r
624 ) {\r
625 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer);\r
5d73d92f 626 } else {\r
304316f4
RN
627 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");\r
628 continue;\r
5d73d92f 629 }\r
5d73d92f 630 }\r
631\r
632 Address += Size;\r
304316f4 633 ShellPrintEx (-1, -1, L"\r\n");\r
5d73d92f 634 } while (!Complete);\r
635 }\r
304316f4 636 ASSERT (ShellStatus == SHELL_SUCCESS);\r
5d73d92f 637\r
304316f4 638Done:\r
5d73d92f 639 if (InputStr != NULL) {\r
304316f4 640 FreePool (InputStr);\r
5d73d92f 641 }\r
642 if (Package != NULL) {\r
643 ShellCommandLineFreeVarList (Package);\r
644 }\r
645 return ShellStatus;\r
646}\r