]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
ShellPkg: Initialize the local pointer to avoid potential suspicious dereference.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / Mm.c
... / ...
CommitLineData
1/** @file\r
2 Main file for Mm shell Debug1 function.\r
3\r
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
5 Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
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
18#include <Library/IoLib.h>\r
19#include <Protocol/PciRootBridgeIo.h>\r
20#include <Protocol/DeviceIo.h>\r
21\r
22typedef enum {\r
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
37\r
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
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
58\r
59/**\r
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
70**/\r
71VOID\r
72EFIAPI\r
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
81 )\r
82{\r
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
96 }\r
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
117}\r
118\r
119/**\r
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
129**/\r
130VOID\r
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
139 )\r
140{\r
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
153 } else {\r
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
198 ASSERT (FALSE);\r
199 break;\r
200 }\r
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
282}\r
283\r
284/**\r
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
288\r
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
293\r
294 @retval TRUE There are PciRootBridgeIo instances in the platform.\r
295 @retval FALSE There isn't PciRootBridgeIo instance in the platform.\r
296**/\r
297BOOLEAN\r
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
303 )\r
304{\r
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 HandleBuffer = NULL;\r
321 Status = gBS->LocateHandleBuffer (\r
322 ByProtocol,\r
323 &gEfiPciRootBridgeIoProtocolGuid,\r
324 NULL,\r
325 &HandleCount,\r
326 &HandleBuffer\r
327 );\r
328 if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {\r
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
335\r
336 //\r
337 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number\r
338 //\r
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
347 }\r
348\r
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
378 }\r
379 }\r
380 if (HandleBuffer != NULL) {\r
381 FreePool (HandleBuffer);\r
382 }\r
383\r
384 return TRUE;\r
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
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
424\r
425 //\r
426 // Parse arguments\r
427 //\r
428 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
429 if (EFI_ERROR (Status)) {\r
430 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
431 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);\r
432 FreePool (ProblemParam);\r
433 ShellStatus = SHELL_INVALID_PARAMETER;\r
434 goto Done;\r
435 } else {\r
436 ASSERT (FALSE);\r
437 }\r
438 } else {\r
439 if (ShellCommandLineGetCount (Package) < 2) {\r
440 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");\r
441 ShellStatus = SHELL_INVALID_PARAMETER;\r
442 goto Done;\r
443 } else if (ShellCommandLineGetCount (Package) > 3) {\r
444 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");\r
445 ShellStatus = SHELL_INVALID_PARAMETER;\r
446 goto Done;\r
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
449 ShellStatus = SHELL_INVALID_PARAMETER;\r
450 goto Done;\r
451 } else {\r
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
460 ShellStatus = SHELL_INVALID_PARAMETER;\r
461 goto Done;\r
462 }\r
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
470 ShellStatus = SHELL_INVALID_PARAMETER;\r
471 goto Done;\r
472 }\r
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
479 ShellStatus = SHELL_INVALID_PARAMETER;\r
480 goto Done;\r
481 }\r
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
487 ShellStatus = SHELL_INVALID_PARAMETER;\r
488 goto Done;\r
489 }\r
490 } else if (ShellCommandLineGetFlag (Package, L"-pcie")) {\r
491 AccessType = ShellMmPciExpress;\r
492 }\r
493 }\r
494\r
495 //\r
496 // Non interactive for a script file or for the specific parameter\r
497 //\r
498 Interactive = TRUE;\r
499 if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) {\r
500 Interactive = FALSE;\r
501 }\r
502\r
503 Temp = ShellCommandLineGetValue (Package, L"-w");\r
504 if (Temp != NULL) {\r
505 Size = ShellStrToUintn (Temp);\r
506 }\r
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
509 ShellStatus = SHELL_INVALID_PARAMETER;\r
510 goto Done;\r
511 }\r
512\r
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
519 }\r
520\r
521 if ((Address & (Size - 1)) != 0) {\r
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
529 ShellStatus = SHELL_INVALID_PARAMETER;\r
530 goto Done;\r
531 }\r
532\r
533 //\r
534 // locate IO protocol interface\r
535 //\r
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
540 ShellStatus = SHELL_NOT_FOUND;\r
541 goto Done;\r
542 }\r
543 if (PciRootBridgeIo == NULL) {\r
544 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address);\r
545 ShellStatus = SHELL_INVALID_PARAMETER;\r
546 goto Done;\r
547 }\r
548 }\r
549\r
550 //\r
551 // Mode 1: Directly set a value\r
552 //\r
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
566 }\r
567\r
568 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value);\r
569 goto Done;\r
570 }\r
571\r
572 //\r
573 // Mode 2: Directly show a value\r
574 //\r
575 if (!Interactive) {\r
576 if (!gEfiShellProtocol->BatchIsActive ()) {\r
577 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);\r
578 }\r
579 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);\r
580\r
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
586 goto Done;\r
587 }\r
588\r
589 //\r
590 // Mode 3: Show or set values in interactive mode\r
591 //\r
592 Complete = FALSE;\r
593 do {\r
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
596 break;\r
597 }\r
598\r
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
604 //\r
605 // wait user input to modify\r
606 //\r
607 if (InputStr != NULL) {\r
608 FreePool (InputStr);\r
609 InputStr = NULL;\r
610 }\r
611 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr);\r
612\r
613 if (InputStr != NULL) {\r
614 //\r
615 // skip space characters\r
616 //\r
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
627 } else {\r
628 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");\r
629 continue;\r
630 }\r
631 }\r
632\r
633 Address += Size;\r
634 ShellPrintEx (-1, -1, L"\r\n");\r
635 } while (!Complete);\r
636 }\r
637 ASSERT (ShellStatus == SHELL_SUCCESS);\r
638\r
639Done:\r
640 if (InputStr != NULL) {\r
641 FreePool (InputStr);\r
642 }\r
643 if (Package != NULL) {\r
644 ShellCommandLineFreeVarList (Package);\r
645 }\r
646 return ShellStatus;\r
647}\r