2 Main file for Mm shell Debug1 function.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2005 - 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UefiShellDebug1CommandsLib.h"
11 #include <Library/ShellLib.h>
12 #include <Library/IoLib.h>
13 #include <Protocol/PciRootBridgeIo.h>
14 #include <Protocol/DeviceIo.h>
18 ShellMmMemoryMappedIo
,
22 } SHELL_MM_ACCESS_TYPE
;
24 CONST UINT16 mShellMmAccessTypeStr
[] = {
25 STRING_TOKEN (STR_MM_MEM
),
26 STRING_TOKEN (STR_MM_MMIO
),
27 STRING_TOKEN (STR_MM_IO
),
28 STRING_TOKEN (STR_MM_PCI
),
29 STRING_TOKEN (STR_MM_PCIE
)
32 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
33 { L
"-mmio", TypeFlag
},
34 { L
"-mem", TypeFlag
},
36 { L
"-pci", TypeFlag
},
37 { L
"-pcie", TypeFlag
},
43 CONST UINT64 mShellMmMaxNumber
[] = {
44 0, MAX_UINT8
, MAX_UINT16
, 0, MAX_UINT32
, 0, 0, 0, MAX_UINT64
46 CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth
[] = {
47 0, EfiPciWidthUint8
, EfiPciWidthUint16
, 0, EfiPciWidthUint32
, 0, 0, 0, EfiPciWidthUint64
49 CONST EFI_CPU_IO_PROTOCOL_WIDTH mShellMmCpuIoWidth
[] = {
50 0, EfiCpuIoWidthUint8
, EfiCpuIoWidthUint16
, 0, EfiCpuIoWidthUint32
, 0, 0, 0, EfiCpuIoWidthUint64
54 Extract the PCI segment, bus, device, function, register from
55 from a PCI or PCIE format of address..
57 @param[in] PciFormat Whether the address is of PCI format of PCIE format.
58 @param[in] Address PCI or PCIE address.
59 @param[out] Segment PCI segment number.
60 @param[out] Bus PCI bus number.
61 @param[out] Device PCI device number.
62 @param[out] Function PCI function number.
63 @param[out] Register PCI register offset.
66 ShellMmDecodePciAddress (
71 OUT UINT8
*Device OPTIONAL
,
72 OUT UINT8
*Function OPTIONAL
,
73 OUT UINT32
*Register OPTIONAL
78 // PCI Configuration Space.The address will have the format ssssbbddffrr,
79 // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register.
81 *Segment
= (UINT32
)(RShiftU64 (Address
, 32) & 0xFFFF);
82 *Bus
= (UINT8
)(((UINT32
)Address
) >> 24);
85 *Device
= (UINT8
)(((UINT32
)Address
) >> 16);
88 if (Function
!= NULL
) {
89 *Function
= (UINT8
)(((UINT32
)Address
) >> 8);
92 if (Register
!= NULL
) {
93 *Register
= (UINT8
)Address
;
97 // PCI Express Configuration Space.The address will have the format ssssssbbddffrrr,
98 // where ssss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register.
100 *Segment
= (UINT32
)(RShiftU64 (Address
, 36) & 0xFFFF);
101 *Bus
= (UINT8
)RShiftU64 (Address
, 28);
102 if (Device
!= NULL
) {
103 *Device
= (UINT8
)(((UINT32
)Address
) >> 20);
106 if (Function
!= NULL
) {
107 *Function
= (UINT8
)(((UINT32
)Address
) >> 12);
110 if (Register
!= NULL
) {
111 *Register
= (UINT32
)(Address
& 0xFFF);
117 Read or write some data from or into the Address.
119 @param[in] AccessType Access type.
120 @param[in] PciRootBridgeIo PciRootBridgeIo instance.
121 @param[in] CpuIo CpuIo instance.
122 @param[in] Read TRUE for read, FALSE for write.
123 @param[in] Addresss The memory location to access.
124 @param[in] Size The size of Buffer in Width sized units.
125 @param[in, out] Buffer The buffer to read into or write from.
129 IN SHELL_MM_ACCESS_TYPE AccessType
,
130 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
131 IN EFI_CPU_IO2_PROTOCOL
*CpuIo
,
139 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM RootBridgeIoMem
;
140 EFI_CPU_IO_PROTOCOL_IO_MEM CpuIoMem
;
147 if (AccessType
== ShellMmMemory
) {
149 CopyMem (Buffer
, (VOID
*)(UINTN
)Address
, Size
);
151 CopyMem ((VOID
*)(UINTN
)Address
, Buffer
, Size
);
154 RootBridgeIoMem
= NULL
;
156 switch (AccessType
) {
158 case ShellMmPciExpress
:
159 ASSERT (PciRootBridgeIo
!= NULL
);
160 ShellMmDecodePciAddress ((BOOLEAN
)(AccessType
== ShellMmPci
), Address
, &Segment
, &Bus
, &Device
, &Function
, &Register
);
162 Status
= PciRootBridgeIo
->Pci
.Read (
164 mShellMmRootBridgeIoWidth
[Size
],
165 EFI_PCI_ADDRESS (Bus
, Device
, Function
, Register
),
170 Status
= PciRootBridgeIo
->Pci
.Write (
172 mShellMmRootBridgeIoWidth
[Size
],
173 EFI_PCI_ADDRESS (Bus
, Device
, Function
, Register
),
179 ASSERT_EFI_ERROR (Status
);
182 case ShellMmMemoryMappedIo
:
183 if (PciRootBridgeIo
!= NULL
) {
184 RootBridgeIoMem
= Read
? PciRootBridgeIo
->Mem
.Read
: PciRootBridgeIo
->Mem
.Write
;
188 CpuIoMem
= Read
? CpuIo
->Mem
.Read
: CpuIo
->Mem
.Write
;
194 if (PciRootBridgeIo
!= NULL
) {
195 RootBridgeIoMem
= Read
? PciRootBridgeIo
->Io
.Read
: PciRootBridgeIo
->Io
.Write
;
199 CpuIoMem
= Read
? CpuIo
->Io
.Read
: CpuIo
->Io
.Write
;
208 Status
= EFI_UNSUPPORTED
;
209 if (RootBridgeIoMem
!= NULL
) {
210 Status
= RootBridgeIoMem (PciRootBridgeIo
, mShellMmRootBridgeIoWidth
[Size
], Address
, 1, Buffer
);
213 if (EFI_ERROR (Status
) && (CpuIoMem
!= NULL
)) {
214 Status
= CpuIoMem (CpuIo
, mShellMmCpuIoWidth
[Size
], Address
, 1, Buffer
);
217 if (EFI_ERROR (Status
)) {
218 if (AccessType
== ShellMmIo
) {
222 *(UINT8
*)Buffer
= IoRead8 ((UINTN
)Address
);
224 IoWrite8 ((UINTN
)Address
, *(UINT8
*)Buffer
);
230 *(UINT16
*)Buffer
= IoRead16 ((UINTN
)Address
);
232 IoWrite16 ((UINTN
)Address
, *(UINT16
*)Buffer
);
238 *(UINT32
*)Buffer
= IoRead32 ((UINTN
)Address
);
240 IoWrite32 ((UINTN
)Address
, *(UINT32
*)Buffer
);
246 *(UINT64
*)Buffer
= IoRead64 ((UINTN
)Address
);
248 IoWrite64 ((UINTN
)Address
, *(UINT64
*)Buffer
);
260 *(UINT8
*)Buffer
= MmioRead8 ((UINTN
)Address
);
262 MmioWrite8 ((UINTN
)Address
, *(UINT8
*)Buffer
);
268 *(UINT16
*)Buffer
= MmioRead16 ((UINTN
)Address
);
270 MmioWrite16 ((UINTN
)Address
, *(UINT16
*)Buffer
);
276 *(UINT32
*)Buffer
= MmioRead32 ((UINTN
)Address
);
278 MmioWrite32 ((UINTN
)Address
, *(UINT32
*)Buffer
);
284 *(UINT64
*)Buffer
= MmioRead64 ((UINTN
)Address
);
286 MmioWrite64 ((UINTN
)Address
, *(UINT64
*)Buffer
);
300 Find the CpuIo instance and PciRootBridgeIo instance in the platform.
301 If there are multiple PciRootBridgeIo instances, the instance which manages
302 the Address is returned.
304 @param[in] AccessType Access type.
305 @param[in] Address Address to access.
306 @param[out] CpuIo Return the CpuIo instance.
307 @param[out] PciRootBridgeIo Return the proper PciRootBridgeIo instance.
309 @retval TRUE There are PciRootBridgeIo instances in the platform.
310 @retval FALSE There isn't PciRootBridgeIo instance in the platform.
313 ShellMmLocateIoProtocol (
314 IN SHELL_MM_ACCESS_TYPE AccessType
,
316 OUT EFI_CPU_IO2_PROTOCOL
**CpuIo
,
317 OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
**PciRootBridgeIo
323 EFI_HANDLE
*HandleBuffer
;
324 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*Io
;
327 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
329 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**)CpuIo
);
330 if (EFI_ERROR (Status
)) {
334 *PciRootBridgeIo
= NULL
;
336 Status
= gBS
->LocateHandleBuffer (
338 &gEfiPciRootBridgeIoProtocolGuid
,
343 if (EFI_ERROR (Status
) || (HandleCount
== 0) || (HandleBuffer
== NULL
)) {
349 if ((AccessType
== ShellMmPci
) || (AccessType
== ShellMmPciExpress
)) {
350 ShellMmDecodePciAddress ((BOOLEAN
)(AccessType
== ShellMmPci
), Address
, &Segment
, &Bus
, NULL
, NULL
, NULL
);
354 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number
356 for (Index
= 0; (Index
< HandleCount
) && (*PciRootBridgeIo
== NULL
); Index
++) {
357 Status
= gBS
->HandleProtocol (
359 &gEfiPciRootBridgeIoProtocolGuid
,
362 if (EFI_ERROR (Status
)) {
366 if ((((AccessType
== ShellMmPci
) || (AccessType
== ShellMmPciExpress
)) && (Io
->SegmentNumber
== Segment
)) ||
367 ((AccessType
== ShellMmIo
) || (AccessType
== ShellMmMemoryMappedIo
))
370 Status
= Io
->Configuration (Io
, (VOID
**)&Descriptors
);
371 if (!EFI_ERROR (Status
)) {
372 while (Descriptors
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
374 // Compare the segment and bus range for PCI/PCIE access
376 if ((Descriptors
->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) &&
377 ((AccessType
== ShellMmPci
) || (AccessType
== ShellMmPciExpress
)) &&
378 ((Bus
>= Descriptors
->AddrRangeMin
) && (Bus
<= Descriptors
->AddrRangeMax
))
381 *PciRootBridgeIo
= Io
;
385 // Compare the address range for MMIO/IO access
387 } else if ((((Descriptors
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) && (AccessType
== ShellMmIo
)) ||
388 ((Descriptors
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) && (AccessType
== ShellMmMemoryMappedIo
))
389 ) && ((Address
>= Descriptors
->AddrRangeMin
) && (Address
<= Descriptors
->AddrRangeMax
))
392 *PciRootBridgeIo
= Io
;
402 if (HandleBuffer
!= NULL
) {
403 FreePool (HandleBuffer
);
410 Function for 'mm' command.
412 @param[in] ImageHandle Handle to the Image (NULL if Internal).
413 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
418 IN EFI_HANDLE ImageHandle
,
419 IN EFI_SYSTEM_TABLE
*SystemTable
423 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
424 EFI_CPU_IO2_PROTOCOL
*CpuIo
;
427 SHELL_MM_ACCESS_TYPE AccessType
;
435 CHAR16
*ProblemParam
;
436 SHELL_STATUS ShellStatus
;
438 BOOLEAN HasPciRootBridgeIo
;
442 ShellStatus
= SHELL_SUCCESS
;
445 AccessType
= ShellMmMemory
;
450 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
451 if (EFI_ERROR (Status
)) {
452 if ((Status
== EFI_VOLUME_CORRUPTED
) && (ProblemParam
!= NULL
)) {
453 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellDebug1HiiHandle
, L
"mm", ProblemParam
);
454 FreePool (ProblemParam
);
455 ShellStatus
= SHELL_INVALID_PARAMETER
;
461 if (ShellCommandLineGetCount (Package
) < 2) {
462 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellDebug1HiiHandle
, L
"mm");
463 ShellStatus
= SHELL_INVALID_PARAMETER
;
465 } else if (ShellCommandLineGetCount (Package
) > 3) {
466 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
467 ShellStatus
= SHELL_INVALID_PARAMETER
;
469 } else if (ShellCommandLineGetFlag (Package
, L
"-w") && (ShellCommandLineGetValue (Package
, L
"-w") == NULL
)) {
470 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_VALUE
), gShellDebug1HiiHandle
, L
"mm", L
"-w");
471 ShellStatus
= SHELL_INVALID_PARAMETER
;
474 if (ShellCommandLineGetFlag (Package
, L
"-mmio")) {
475 AccessType
= ShellMmMemoryMappedIo
;
476 if ( ShellCommandLineGetFlag (Package
, L
"-mem")
477 || ShellCommandLineGetFlag (Package
, L
"-io")
478 || ShellCommandLineGetFlag (Package
, L
"-pci")
479 || ShellCommandLineGetFlag (Package
, L
"-pcie")
482 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
483 ShellStatus
= SHELL_INVALID_PARAMETER
;
486 } else if (ShellCommandLineGetFlag (Package
, L
"-mem")) {
487 AccessType
= ShellMmMemory
;
488 if ( ShellCommandLineGetFlag (Package
, L
"-io")
489 || ShellCommandLineGetFlag (Package
, L
"-pci")
490 || ShellCommandLineGetFlag (Package
, L
"-pcie")
493 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
494 ShellStatus
= SHELL_INVALID_PARAMETER
;
497 } else if (ShellCommandLineGetFlag (Package
, L
"-io")) {
498 AccessType
= ShellMmIo
;
499 if ( ShellCommandLineGetFlag (Package
, L
"-pci")
500 || ShellCommandLineGetFlag (Package
, L
"-pcie")
503 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
504 ShellStatus
= SHELL_INVALID_PARAMETER
;
507 } else if (ShellCommandLineGetFlag (Package
, L
"-pci")) {
508 AccessType
= ShellMmPci
;
509 if (ShellCommandLineGetFlag (Package
, L
"-pcie")
512 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
513 ShellStatus
= SHELL_INVALID_PARAMETER
;
516 } else if (ShellCommandLineGetFlag (Package
, L
"-pcie")) {
517 AccessType
= ShellMmPciExpress
;
522 // Non interactive for a script file or for the specific parameter
525 if (gEfiShellProtocol
->BatchIsActive () || ShellCommandLineGetFlag (Package
, L
"-n")) {
529 Temp
= ShellCommandLineGetValue (Package
, L
"-w");
531 Size
= ShellStrToUintn (Temp
);
534 if ((Size
!= 1) && (Size
!= 2) && (Size
!= 4) && (Size
!= 8)) {
535 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM_VAL
), gShellDebug1HiiHandle
, L
"mm", Temp
, L
"-w");
536 ShellStatus
= SHELL_INVALID_PARAMETER
;
540 Temp
= ShellCommandLineGetRawValue (Package
, 1);
541 Status
= ShellConvertStringToUint64 (Temp
, &Address
, TRUE
, FALSE
);
542 if (EFI_ERROR (Status
)) {
543 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
544 ShellStatus
= SHELL_INVALID_PARAMETER
;
548 if ((Address
& (Size
- 1)) != 0) {
549 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_NOT_ALIGNED
), gShellDebug1HiiHandle
, L
"mm", Address
);
550 ShellStatus
= SHELL_INVALID_PARAMETER
;
555 // locate IO protocol interface
557 HasPciRootBridgeIo
= ShellMmLocateIoProtocol (AccessType
, Address
, &CpuIo
, &PciRootBridgeIo
);
558 if ((AccessType
== ShellMmPci
) || (AccessType
== ShellMmPciExpress
)) {
559 if (!HasPciRootBridgeIo
) {
560 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PCIRBIO_NF
), gShellDebug1HiiHandle
, L
"mm");
561 ShellStatus
= SHELL_NOT_FOUND
;
565 if (PciRootBridgeIo
== NULL
) {
566 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE
), gShellDebug1HiiHandle
, L
"mm", Address
);
567 ShellStatus
= SHELL_INVALID_PARAMETER
;
573 // Mode 1: Directly set a value
575 Temp
= ShellCommandLineGetRawValue (Package
, 2);
577 Status
= ShellConvertStringToUint64 (Temp
, &Value
, TRUE
, FALSE
);
578 if (EFI_ERROR (Status
)) {
579 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
580 ShellStatus
= SHELL_INVALID_PARAMETER
;
584 if (Value
> mShellMmMaxNumber
[Size
]) {
585 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
586 ShellStatus
= SHELL_INVALID_PARAMETER
;
590 ShellMmAccess (AccessType
, PciRootBridgeIo
, CpuIo
, FALSE
, Address
, Size
, &Value
);
595 // Mode 2: Directly show a value
598 if (!gEfiShellProtocol
->BatchIsActive ()) {
599 ShellPrintHiiEx (-1, -1, NULL
, mShellMmAccessTypeStr
[AccessType
], gShellDebug1HiiHandle
);
602 ShellMmAccess (AccessType
, PciRootBridgeIo
, CpuIo
, TRUE
, Address
, Size
, &Buffer
);
604 if (!gEfiShellProtocol
->BatchIsActive ()) {
605 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS
), gShellDebug1HiiHandle
, Address
);
608 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF
), gShellDebug1HiiHandle
, Size
* 2, Buffer
& mShellMmMaxNumber
[Size
]);
609 ShellPrintEx (-1, -1, L
"\r\n");
614 // Mode 3: Show or set values in interactive mode
618 ShellMmAccess (AccessType
, PciRootBridgeIo
, CpuIo
, TRUE
, Address
, Size
, &Buffer
);
619 ShellPrintHiiEx (-1, -1, NULL
, mShellMmAccessTypeStr
[AccessType
], gShellDebug1HiiHandle
);
620 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS
), gShellDebug1HiiHandle
, Address
);
621 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF
), gShellDebug1HiiHandle
, Size
* 2, Buffer
& mShellMmMaxNumber
[Size
]);
622 ShellPrintEx (-1, -1, L
" > ");
624 // wait user input to modify
626 if (InputStr
!= NULL
) {
631 ShellPromptForResponse (ShellPromptResponseTypeFreeform
, NULL
, (VOID
**)&InputStr
);
633 if (InputStr
!= NULL
) {
635 // skip space characters
637 for (Index
= 0; InputStr
[Index
] == ' '; Index
++) {
640 if (InputStr
[Index
] != CHAR_NULL
) {
641 if ((InputStr
[Index
] == '.') || (InputStr
[Index
] == 'q') || (InputStr
[Index
] == 'Q')) {
643 } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr
+ Index
, &Buffer
, TRUE
, TRUE
)) &&
644 (Buffer
<= mShellMmMaxNumber
[Size
])
647 ShellMmAccess (AccessType
, PciRootBridgeIo
, CpuIo
, FALSE
, Address
, Size
, &Buffer
);
649 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_MM_ERROR
), gShellDebug1HiiHandle
, L
"mm");
656 ShellPrintEx (-1, -1, L
"\r\n");
660 ASSERT (ShellStatus
== SHELL_SUCCESS
);
663 if (InputStr
!= NULL
) {
667 if (Package
!= NULL
) {
668 ShellCommandLineFreeVarList (Package
);