2 Main file for Mm shell Debug1 function.
4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2005 - 2014, 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
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.
16 #include "UefiShellDebug1CommandsLib.h"
17 #include <Library/ShellLib.h>
18 #include <Protocol/PciRootBridgeIo.h>
19 #include <Protocol/DeviceIo.h>
29 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
40 STATIC CONST UINT64 MaxNum
[9] = { 0xff, 0xffff, 0xffffffff, 0xffffffffffffffffULL
};
43 Read some data into a buffer from memory.
45 @param[in] Width The width of each read.
46 @param[in] Addresss The memory location to start reading at.
47 @param[in] Size The size of Buffer in Width sized units.
48 @param[out] Buffer The buffer to read into.
53 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
60 // This function is defective. This ASSERT prevents the defect from affecting anything.
64 if (Width
== EfiPciWidthUint8
) {
65 *(UINT8
*) Buffer
= *(UINT8
*) (UINTN
) Address
;
67 } else if (Width
== EfiPciWidthUint16
) {
68 *(UINT16
*) Buffer
= *(UINT16
*) (UINTN
) Address
;
70 } else if (Width
== EfiPciWidthUint32
) {
71 *(UINT32
*) Buffer
= *(UINT32
*) (UINTN
) Address
;
73 } else if (Width
== EfiPciWidthUint64
) {
74 *(UINT64
*) Buffer
= *(UINT64
*) (UINTN
) Address
;
77 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_READ_ERROR
), gShellDebug1HiiHandle
, L
"mm");
85 Write some data to memory.
87 @param[in] Width The width of each write.
88 @param[in] Addresss The memory location to start writing at.
89 @param[in] Size The size of Buffer in Width sized units.
90 @param[in] Buffer The buffer to write from.
95 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
102 // This function is defective. This ASSERT prevents the defect from affecting anything.
106 if (Width
== EfiPciWidthUint8
) {
107 *(UINT8
*) (UINTN
) Address
= *(UINT8
*) Buffer
;
109 } else if (Width
== EfiPciWidthUint16
) {
110 *(UINT16
*) (UINTN
) Address
= *(UINT16
*) Buffer
;
112 } else if (Width
== EfiPciWidthUint32
) {
113 *(UINT32
*) (UINTN
) Address
= *(UINT32
*) Buffer
;
115 } else if (Width
== EfiPciWidthUint64
) {
116 *(UINT64
*) (UINTN
) Address
= *(UINT64
*) Buffer
;
129 Convert a string to it's hex data.
131 @param[in] str The pointer to the string of hex data.
132 @param[out] data The pointer to the buffer to fill. Valid upon a TRUE return.
134 @retval TRUE The conversion was successful.
135 @retval FALSE The conversion failed.
150 // convert hex digits
154 while (TempChar
!= CHAR_NULL
) {
155 if (TempChar
>= 'a' && TempChar
<= 'f') {
156 TempChar
-= 'a' - 'A';
159 if (TempChar
== ' ') {
163 if ((TempChar
>= '0' && TempChar
<= '9') || (TempChar
>= 'A' && TempChar
<= 'F')) {
164 TempUint
= (TempUint
<< 4) | (TempChar
- (TempChar
>= 'A' ? 'A' - 10 : '0'));
179 Get the PCI-E Address from a PCI address format 0x0000ssbbddffrrr
180 where ss is SEGMENT, bb is BUS, dd is DEVICE, ff is FUNCTION
181 and rrr is REGISTER (extension format for PCI-E).
183 @param[in] InputAddress PCI address format on input.
184 @param[out]PciEAddress PCI-E address extention format.
188 GetPciEAddressFromInputAddress (
189 IN UINT64 InputAddress
,
190 OUT UINT64
*PciEAddress
193 *PciEAddress
= RShiftU64(InputAddress
& ~(UINT64
) 0xFFF, 4);
194 *PciEAddress
+= LShiftU64((UINT16
) InputAddress
& 0x0FFF, 32);
198 Function for 'mm' command.
200 @param[in] ImageHandle Handle to the Image (NULL if Internal).
201 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
206 IN EFI_HANDLE ImageHandle
,
207 IN EFI_SYSTEM_TABLE
*SystemTable
211 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*IoDev
;
215 UINT32 SegmentNumber
;
216 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
;
217 EFI_ACCESS_TYPE AccessType
;
225 EFI_HANDLE
*HandleBuffer
;
229 CHAR16
*ProblemParam
;
230 SHELL_STATUS ShellStatus
;
240 ShellStatus
= SHELL_SUCCESS
;
246 Width
= EfiPciWidthUint8
;
248 AccessType
= EfiMemory
;
253 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
254 if (EFI_ERROR(Status
)) {
255 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
256 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellDebug1HiiHandle
, L
"mm", ProblemParam
);
257 FreePool(ProblemParam
);
258 ShellStatus
= SHELL_INVALID_PARAMETER
;
264 if (ShellCommandLineGetCount(Package
) < 2) {
265 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellDebug1HiiHandle
, L
"mm");
266 ShellStatus
= SHELL_INVALID_PARAMETER
;
268 } else if (ShellCommandLineGetCount(Package
) > 3) {
269 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
270 ShellStatus
= SHELL_INVALID_PARAMETER
;
272 } else if (ShellCommandLineGetFlag(Package
, L
"-w") && ShellCommandLineGetValue(Package
, L
"-w") == NULL
) {
273 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_VALUE
), gShellDebug1HiiHandle
, L
"mm", L
"-w");
274 ShellStatus
= SHELL_INVALID_PARAMETER
;
277 if (ShellCommandLineGetFlag(Package
, L
"-mmio")) {
278 AccessType
= EFIMemoryMappedIo
;
279 if (ShellCommandLineGetFlag(Package
, L
"-mem")
280 ||ShellCommandLineGetFlag(Package
, L
"-io")
281 ||ShellCommandLineGetFlag(Package
, L
"-pci")
282 ||ShellCommandLineGetFlag(Package
, L
"-pcie")
284 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
285 ShellStatus
= SHELL_INVALID_PARAMETER
;
288 } else if (ShellCommandLineGetFlag(Package
, L
"-mem")) {
289 AccessType
= EfiMemory
;
290 if (ShellCommandLineGetFlag(Package
, L
"-io")
291 ||ShellCommandLineGetFlag(Package
, L
"-pci")
292 ||ShellCommandLineGetFlag(Package
, L
"-pcie")
294 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
295 ShellStatus
= SHELL_INVALID_PARAMETER
;
298 } else if (ShellCommandLineGetFlag(Package
, L
"-io")) {
300 if (ShellCommandLineGetFlag(Package
, L
"-pci")
301 ||ShellCommandLineGetFlag(Package
, L
"-pcie")
303 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
304 ShellStatus
= SHELL_INVALID_PARAMETER
;
307 } else if (ShellCommandLineGetFlag(Package
, L
"-pci")) {
308 AccessType
= EfiPciConfig
;
309 if (ShellCommandLineGetFlag(Package
, L
"-pcie")
311 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellDebug1HiiHandle
, L
"mm");
312 ShellStatus
= SHELL_INVALID_PARAMETER
;
315 } else if (ShellCommandLineGetFlag(Package
, L
"-pcie")) {
316 AccessType
= EfiPciEConfig
;
321 // Non interactive for a script file or for the specific parameter
323 if (gEfiShellProtocol
->BatchIsActive() || ShellCommandLineGetFlag (Package
, L
"-n")) {
327 Temp
= ShellCommandLineGetValue(Package
, L
"-w");
329 ItemValue
= ShellStrToUintn (Temp
);
333 Width
= EfiPciWidthUint8
;
338 Width
= EfiPciWidthUint16
;
343 Width
= EfiPciWidthUint32
;
348 Width
= EfiPciWidthUint64
;
353 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM_VAL
), gShellDebug1HiiHandle
, L
"mm", Temp
, L
"-w");
354 ShellStatus
= SHELL_INVALID_PARAMETER
;
359 Temp
= ShellCommandLineGetRawValue(Package
, 1);
360 if (!ShellIsHexOrDecimalNumber(Temp
, TRUE
, FALSE
) || EFI_ERROR(ShellConvertStringToUint64(Temp
, (UINT64
*)&Address
, TRUE
, FALSE
))) {
361 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
362 ShellStatus
= SHELL_INVALID_PARAMETER
;
366 Temp
= ShellCommandLineGetRawValue(Package
, 2);
369 // Per spec if value is specified, then -n is assumed.
373 if (!ShellIsHexOrDecimalNumber(Temp
, TRUE
, FALSE
) || EFI_ERROR(ShellConvertStringToUint64(Temp
, &Value
, TRUE
, FALSE
))) {
374 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
375 ShellStatus
= SHELL_INVALID_PARAMETER
;
381 ShellStatus
= SHELL_INVALID_PARAMETER
;
386 if (Value
> 0xFFFF) {
387 ShellStatus
= SHELL_INVALID_PARAMETER
;
392 if (Value
> 0xFFFFFFFF) {
393 ShellStatus
= SHELL_INVALID_PARAMETER
;
401 if (ShellStatus
!= SHELL_SUCCESS
) {
402 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellDebug1HiiHandle
, L
"mm", Temp
);
403 ShellStatus
= SHELL_INVALID_PARAMETER
;
408 if ((Address
& (Size
- 1)) != 0) {
409 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_NOT_ALIGNED
), gShellDebug1HiiHandle
, L
"mm", Address
);
410 ShellStatus
= SHELL_INVALID_PARAMETER
;
414 // locate DeviceIO protocol interface
416 if (AccessType
!= EfiMemory
) {
417 Status
= gBS
->LocateHandleBuffer (
419 &gEfiPciRootBridgeIoProtocolGuid
,
424 if (EFI_ERROR (Status
)) {
425 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PCIRBIO_NF
), gShellDebug1HiiHandle
, L
"mm");
426 ShellStatus
= SHELL_NOT_FOUND
;
430 // In the case of PCI or PCIE
431 // Get segment number and mask the segment bits in Address
433 if (AccessType
== EfiPciEConfig
) {
434 SegmentNumber
= (UINT32
) RShiftU64 (Address
, 36) & 0xff;
435 Address
&= 0xfffffffffULL
;
437 if (AccessType
== EfiPciConfig
) {
438 SegmentNumber
= (UINT32
) RShiftU64 (Address
, 32) & 0xff;
439 Address
&= 0xffffffff;
443 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment number
445 for (Index
= 0; Index
< BufferSize
; Index
++) {
446 Status
= gBS
->HandleProtocol (
448 &gEfiPciRootBridgeIoProtocolGuid
,
451 if (EFI_ERROR (Status
)) {
454 if (IoDev
->SegmentNumber
!= SegmentNumber
) {
459 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_SEGMENT_NOT_FOUND
), gShellDebug1HiiHandle
, L
"mm", SegmentNumber
);
460 ShellStatus
= SHELL_INVALID_PARAMETER
;
465 if (AccessType
== EfiIo
&& Address
+ Size
> 0x10000) {
466 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS_RANGE
), gShellDebug1HiiHandle
, L
"mm");
467 ShellStatus
= SHELL_INVALID_PARAMETER
;
471 if (AccessType
== EfiPciEConfig
) {
472 GetPciEAddressFromInputAddress (Address
, &PciEAddress
);
478 if (ShellCommandLineGetRawValue(Package
, 2) != NULL
) {
479 if (AccessType
== EFIMemoryMappedIo
) {
480 IoDev
->Mem
.Write (IoDev
, Width
, Address
, 1, &Value
);
481 } else if (AccessType
== EfiIo
) {
482 IoDev
->Io
.Write (IoDev
, Width
, Address
, 1, &Value
);
483 } else if (AccessType
== EfiPciConfig
) {
484 IoDev
->Pci
.Write (IoDev
, Width
, Address
, 1, &Value
);
485 } else if (AccessType
== EfiPciEConfig
) {
486 IoDev
->Pci
.Write (IoDev
, Width
, PciEAddress
, 1, &Value
);
488 WriteMem (Width
, Address
, 1, &Value
);
491 ASSERT(ShellStatus
== SHELL_SUCCESS
);
497 // non-interactive mode
501 if (AccessType
== EFIMemoryMappedIo
) {
502 if (!gEfiShellProtocol
->BatchIsActive()) {
503 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_MMIO
), gShellDebug1HiiHandle
);
505 IoDev
->Mem
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
506 } else if (AccessType
== EfiIo
) {
507 if (!gEfiShellProtocol
->BatchIsActive()) {
508 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_IO
), gShellDebug1HiiHandle
);
510 IoDev
->Io
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
511 } else if (AccessType
== EfiPciConfig
) {
512 if (!gEfiShellProtocol
->BatchIsActive()) {
513 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_PCI
), gShellDebug1HiiHandle
);
515 IoDev
->Pci
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
516 } else if (AccessType
== EfiPciEConfig
) {
517 if (!gEfiShellProtocol
->BatchIsActive()) {
518 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_PCIE
), gShellDebug1HiiHandle
);
520 IoDev
->Pci
.Read (IoDev
, Width
, PciEAddress
, 1, &Buffer
);
522 if (!gEfiShellProtocol
->BatchIsActive()) {
523 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_MEM
), gShellDebug1HiiHandle
);
525 ReadMem (Width
, Address
, 1, &Buffer
);
527 if (!gEfiShellProtocol
->BatchIsActive()) {
528 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS
), gShellDebug1HiiHandle
, Address
);
531 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF2
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
532 } else if (Size
== 2) {
533 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF4
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
534 } else if (Size
== 4) {
535 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF8
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
536 } else if (Size
== 8) {
537 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF16
), gShellDebug1HiiHandle
, Buffer
);
540 ShellPrintEx(-1, -1, L
"\r\n");
542 ASSERT(ShellStatus
== SHELL_SUCCESS
);
550 if (AccessType
== EfiIo
&& Address
+ Size
> 0x10000) {
551 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS_RANGE2
), gShellDebug1HiiHandle
, L
"mm");
556 if (AccessType
== EFIMemoryMappedIo
) {
557 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_MMIO
), gShellDebug1HiiHandle
);
558 IoDev
->Mem
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
559 } else if (AccessType
== EfiIo
) {
560 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_IO
), gShellDebug1HiiHandle
);
561 IoDev
->Io
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
562 } else if (AccessType
== EfiPciConfig
) {
563 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_PCI
), gShellDebug1HiiHandle
);
564 IoDev
->Pci
.Read (IoDev
, Width
, Address
, 1, &Buffer
);
565 } else if (AccessType
== EfiPciEConfig
) {
566 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_PCIE
), gShellDebug1HiiHandle
);
567 IoDev
->Pci
.Read (IoDev
, Width
, PciEAddress
, 1, &Buffer
);
569 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_MEM
), gShellDebug1HiiHandle
);
570 ReadMem (Width
, Address
, 1, &Buffer
);
573 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_ADDRESS
), gShellDebug1HiiHandle
, Address
);
576 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF2
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
577 } else if (Size
== 2) {
578 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF4
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
579 } else if (Size
== 4) {
580 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF8
), gShellDebug1HiiHandle
, (UINTN
)Buffer
);
581 } else if (Size
== 8) {
582 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_BUF16
), gShellDebug1HiiHandle
, Buffer
);
584 ShellPrintEx(-1, -1, L
" > ");
586 // wait user input to modify
588 if (InputStr
!= NULL
) {
592 ShellPromptForResponse(ShellPromptResponseTypeFreeform
, NULL
, (VOID
**)&InputStr
);
595 // skip space characters
597 for (Index
= 0; InputStr
!= NULL
&& InputStr
[Index
] == ' '; Index
++);
600 // parse input string
602 if (InputStr
!= NULL
&& (InputStr
[Index
] == '.' || InputStr
[Index
] == 'q' || InputStr
[Index
] == 'Q')) {
604 } else if (InputStr
== NULL
|| InputStr
[Index
] == CHAR_NULL
) {
606 // Continue to next address
608 } else if (GetHex (InputStr
+ Index
, &Buffer
) && Buffer
<= MaxNum
[Width
]) {
609 if (AccessType
== EFIMemoryMappedIo
) {
610 IoDev
->Mem
.Write (IoDev
, Width
, Address
, 1, &Buffer
);
611 } else if (AccessType
== EfiIo
) {
612 IoDev
->Io
.Write (IoDev
, Width
, Address
, 1, &Buffer
);
613 } else if (AccessType
== EfiPciConfig
) {
614 IoDev
->Pci
.Write (IoDev
, Width
, Address
, 1, &Buffer
);
615 } else if (AccessType
== EfiPciEConfig
) {
616 IoDev
->Pci
.Write (IoDev
, Width
, PciEAddress
, 1, &Buffer
);
618 WriteMem (Width
, Address
, 1, &Buffer
);
621 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MM_ERROR
), gShellDebug1HiiHandle
, L
"mm");
623 // PrintToken (STRING_TOKEN (STR_IOMOD_ERROR), HiiHandle);
627 if (AccessType
== EfiPciEConfig
) {
628 GetPciEAddressFromInputAddress (Address
, &PciEAddress
);
630 ShellPrintEx(-1, -1, L
"\r\n");
634 ASSERT(ShellStatus
== SHELL_SUCCESS
);
637 if (InputStr
!= NULL
) {
640 if (HandleBuffer
!= NULL
) {
641 FreePool (HandleBuffer
);
643 if (Package
!= NULL
) {
644 ShellCommandLineFreeVarList (Package
);