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