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