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