Mm.c revision 304316f430519b5a84cf7402d1721d22ba6f94b7
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 22typedef enum { 23 ShellMmMemory, 24 ShellMmMemoryMappedIo, 25 ShellMmIo, 26 ShellMmPci, 27 ShellMmPciExpress 28} SHELL_MM_ACCESS_TYPE; 29 30CONST 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 38STATIC 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 49CONST UINT64 mShellMmMaxNumber[] = { 50 0, MAX_UINT8, MAX_UINT16, 0, MAX_UINT32, 0, 0, 0, MAX_UINT64 51}; 52CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth[] = { 53 0, EfiPciWidthUint8, EfiPciWidthUint16, 0, EfiPciWidthUint32, 0, 0, 0, EfiPciWidthUint64 54}; 55CONST 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**/ 71VOID 72EFIAPI 73ShellMmDecodePciAddress ( 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**/ 130VOID 131ShellMmAccess ( 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**/ 297BOOLEAN 298ShellMmLocateIoProtocol ( 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 Status = gBS->LocateHandleBuffer ( 321 ByProtocol, 322 &gEfiPciRootBridgeIoProtocolGuid, 323 NULL, 324 &HandleCount, 325 &HandleBuffer 326 ); 327 if (EFI_ERROR (Status) || (HandleCount == 0)) { 328 return FALSE; 329 } 330 331 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { 332 ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL); 333 } 334 335 // 336 // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number 337 // 338 for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) { 339 Status = gBS->HandleProtocol ( 340 HandleBuffer[Index], 341 &gEfiPciRootBridgeIoProtocolGuid, 342 (VOID *) &Io 343 ); 344 if (EFI_ERROR (Status)) { 345 continue; 346 } 347 348 if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) || 349 ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo)) 350 ) { 351 Status = Io->Configuration (Io, (VOID **) &Descriptors); 352 if (!EFI_ERROR (Status)) { 353 while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) { 354 // 355 // Compare the segment and bus range for PCI/PCIE access 356 // 357 if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) && 358 ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && 359 ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax)) 360 ) { 361 *PciRootBridgeIo = Io; 362 break; 363 364 // 365 // Compare the address range for MMIO/IO access 366 // 367 } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) || 368 ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo)) 369 ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax)) 370 ) { 371 *PciRootBridgeIo = Io; 372 break; 373 } 374 Descriptors++; 375 } 376 } 377 } 378 } 379 if (HandleBuffer != NULL) { 380 FreePool (HandleBuffer); 381 } 382 383 return TRUE; 384} 385 386/** 387 Function for 'mm' command. 388 389 @param[in] ImageHandle Handle to the Image (NULL if Internal). 390 @param[in] SystemTable Pointer to the System Table (NULL if Internal). 391**/ 392SHELL_STATUS 393EFIAPI 394ShellCommandRunMm ( 395 IN EFI_HANDLE ImageHandle, 396 IN EFI_SYSTEM_TABLE *SystemTable 397 ) 398{ 399 EFI_STATUS Status; 400 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; 401 EFI_CPU_IO2_PROTOCOL *CpuIo; 402 UINT64 Address; 403 UINT64 Value; 404 SHELL_MM_ACCESS_TYPE AccessType; 405 UINT64 Buffer; 406 UINTN Index; 407 UINTN Size; 408 BOOLEAN Complete; 409 CHAR16 *InputStr; 410 BOOLEAN Interactive; 411 LIST_ENTRY *Package; 412 CHAR16 *ProblemParam; 413 SHELL_STATUS ShellStatus; 414 CONST CHAR16 *Temp; 415 BOOLEAN HasPciRootBridgeIo; 416 417 Value = 0; 418 Address = 0; 419 ShellStatus = SHELL_SUCCESS; 420 InputStr = NULL; 421 Size = 1; 422 AccessType = ShellMmMemory; 423 424 // 425 // Parse arguments 426 // 427 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); 428 if (EFI_ERROR (Status)) { 429 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { 430 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam); 431 FreePool (ProblemParam); 432 ShellStatus = SHELL_INVALID_PARAMETER; 433 goto Done; 434 } else { 435 ASSERT (FALSE); 436 } 437 } else { 438 if (ShellCommandLineGetCount (Package) < 2) { 439 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm"); 440 ShellStatus = SHELL_INVALID_PARAMETER; 441 goto Done; 442 } else if (ShellCommandLineGetCount (Package) > 3) { 443 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); 444 ShellStatus = SHELL_INVALID_PARAMETER; 445 goto Done; 446 } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) { 447 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w"); 448 ShellStatus = SHELL_INVALID_PARAMETER; 449 goto Done; 450 } else { 451 if (ShellCommandLineGetFlag (Package, L"-mmio")) { 452 AccessType = ShellMmMemoryMappedIo; 453 if (ShellCommandLineGetFlag (Package, L"-mem") 454 || ShellCommandLineGetFlag (Package, L"-io") 455 || ShellCommandLineGetFlag (Package, L"-pci") 456 || ShellCommandLineGetFlag (Package, L"-pcie") 457 ) { 458 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); 459 ShellStatus = SHELL_INVALID_PARAMETER; 460 goto Done; 461 } 462 } else if (ShellCommandLineGetFlag (Package, L"-mem")) { 463 AccessType = ShellMmMemory; 464 if (ShellCommandLineGetFlag (Package, L"-io") 465 || ShellCommandLineGetFlag (Package, L"-pci") 466 || ShellCommandLineGetFlag (Package, L"-pcie") 467 ) { 468 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); 469 ShellStatus = SHELL_INVALID_PARAMETER; 470 goto Done; 471 } 472 } else if (ShellCommandLineGetFlag (Package, L"-io")) { 473 AccessType = ShellMmIo; 474 if (ShellCommandLineGetFlag (Package, L"-pci") 475 || ShellCommandLineGetFlag (Package, L"-pcie") 476 ) { 477 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); 478 ShellStatus = SHELL_INVALID_PARAMETER; 479 goto Done; 480 } 481 } else if (ShellCommandLineGetFlag (Package, L"-pci")) { 482 AccessType = ShellMmPci; 483 if (ShellCommandLineGetFlag (Package, L"-pcie") 484 ) { 485 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm"); 486 ShellStatus = SHELL_INVALID_PARAMETER; 487 goto Done; 488 } 489 } else if (ShellCommandLineGetFlag (Package, L"-pcie")) { 490 AccessType = ShellMmPciExpress; 491 } 492 } 493 494 // 495 // Non interactive for a script file or for the specific parameter 496 // 497 Interactive = TRUE; 498 if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) { 499 Interactive = FALSE; 500 } 501 502 Temp = ShellCommandLineGetValue (Package, L"-w"); 503 if (Temp != NULL) { 504 Size = ShellStrToUintn (Temp); 505 } 506 if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) { 507 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w"); 508 ShellStatus = SHELL_INVALID_PARAMETER; 509 goto Done; 510 } 511 512 Temp = ShellCommandLineGetRawValue (Package, 1); 513 Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE); 514 if (EFI_ERROR (Status)) { 515 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); 516 ShellStatus = SHELL_INVALID_PARAMETER; 517 goto Done; 518 } 519 520 if ((Address & (Size - 1)) != 0) { 521 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address); 522 ShellStatus = SHELL_INVALID_PARAMETER; 523 goto Done; 524 } 525 526 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) { 527 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_IO_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm"); 528 ShellStatus = SHELL_INVALID_PARAMETER; 529 goto Done; 530 } 531 532 // 533 // locate IO protocol interface 534 // 535 HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo); 536 if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) { 537 if (!HasPciRootBridgeIo) { 538 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm"); 539 ShellStatus = SHELL_NOT_FOUND; 540 goto Done; 541 } 542 if (PciRootBridgeIo == NULL) { 543 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address); 544 ShellStatus = SHELL_INVALID_PARAMETER; 545 goto Done; 546 } 547 } 548 549 // 550 // Mode 1: Directly set a value 551 // 552 Temp = ShellCommandLineGetRawValue (Package, 2); 553 if (Temp != NULL) { 554 Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE); 555 if (EFI_ERROR (Status)) { 556 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); 557 ShellStatus = SHELL_INVALID_PARAMETER; 558 goto Done; 559 } 560 561 if (Value > mShellMmMaxNumber[Size]) { 562 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp); 563 ShellStatus = SHELL_INVALID_PARAMETER; 564 goto Done; 565 } 566 567 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value); 568 goto Done; 569 } 570 571 // 572 // Mode 2: Directly show a value 573 // 574 if (!Interactive) { 575 if (!gEfiShellProtocol->BatchIsActive ()) { 576 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); 577 } 578 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); 579 580 if (!gEfiShellProtocol->BatchIsActive ()) { 581 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); 582 } 583 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); 584 ShellPrintEx (-1, -1, L"\r\n"); 585 goto Done; 586 } 587 588 // 589 // Mode 3: Show or set values in interactive mode 590 // 591 Complete = FALSE; 592 do { 593 if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) { 594 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm"); 595 break; 596 } 597 598 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer); 599 ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle); 600 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address); 601 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]); 602 ShellPrintEx (-1, -1, L" > "); 603 // 604 // wait user input to modify 605 // 606 if (InputStr != NULL) { 607 FreePool (InputStr); 608 InputStr = NULL; 609 } 610 ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr); 611 612 if (InputStr != NULL) { 613 // 614 // skip space characters 615 // 616 for (Index = 0; InputStr[Index] == ' '; Index++); 617 } 618 619 if ((InputStr != NULL) && (InputStr[Index] != CHAR_NULL)) { 620 if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) { 621 Complete = TRUE; 622 } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) && 623 (Buffer <= mShellMmMaxNumber[Size]) 624 ) { 625 ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer); 626 } else { 627 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm"); 628 continue; 629 } 630 } 631 632 Address += Size; 633 ShellPrintEx (-1, -1, L"\r\n"); 634 } while (!Complete); 635 } 636 ASSERT (ShellStatus == SHELL_SUCCESS); 637 638Done: 639 if (InputStr != NULL) { 640 FreePool (InputStr); 641 } 642 if (Package != NULL) { 643 ShellCommandLineFreeVarList (Package); 644 } 645 return ShellStatus; 646} 647