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 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 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 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 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