1 /** @file 2 Implementation for S3 Boot Script Saver driver. 3 4 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> 5 6 7 This program and the accompanying materials are licensed and made available under 8 9 the terms and conditions of the BSD License that accompanies this distribution. 10 11 The full text of the license may be found at 12 13 http://opensource.org/licenses/bsd-license.php. 14 15 16 17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 18 19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 20 21 22 23 24 **/ 25 26 #include "InternalBootScriptSave.h" 27 28 EFI_HANDLE mHandle = NULL; 29 EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave = { 30 BootScriptWrite, 31 BootScriptCloseTable 32 }; 33 34 /** 35 Internal function to add IO write opcode to the table. BootScriptIoWrite(IN VA_LIST Marker)36 37 @param Marker The variable argument list to get the opcode 38 and associated attributes. 39 40 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 41 @retval EFI_SUCCESS Opcode is added. 42 43 **/ 44 EFI_STATUS 45 BootScriptIoWrite ( 46 IN VA_LIST Marker 47 ) 48 { 49 S3_BOOT_SCRIPT_LIB_WIDTH Width; 50 UINT64 Address; 51 UINTN Count; 52 UINT8 *Buffer; 53 54 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 55 Address = VA_ARG (Marker, UINT64); 56 Count = VA_ARG (Marker, UINTN); 57 Buffer = VA_ARG (Marker, UINT8 *); 58 59 return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer); 60 } 61 62 /** 63 Internal function to add IO read/write opcode to the table. BootScriptIoReadWrite(IN VA_LIST Marker)64 65 @param Marker The variable argument list to get the opcode 66 and associated attributes. 67 68 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 69 @retval EFI_SUCCESS Opcode is added. 70 71 **/ 72 EFI_STATUS 73 BootScriptIoReadWrite ( 74 IN VA_LIST Marker 75 ) 76 { 77 S3_BOOT_SCRIPT_LIB_WIDTH Width; 78 UINT64 Address; 79 UINT8 *Data; 80 UINT8 *DataMask; 81 82 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 83 Address = VA_ARG (Marker, UINT64); 84 Data = VA_ARG (Marker, UINT8 *); 85 DataMask = VA_ARG (Marker, UINT8 *); 86 87 return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask); 88 } 89 90 /** 91 Internal function to add memory write opcode to the table. BootScriptMemWrite(IN VA_LIST Marker)92 93 @param Marker The variable argument list to get the opcode 94 and associated attributes. 95 96 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 97 @retval EFI_SUCCESS Opcode is added. 98 99 **/ 100 EFI_STATUS 101 BootScriptMemWrite ( 102 IN VA_LIST Marker 103 ) 104 { 105 S3_BOOT_SCRIPT_LIB_WIDTH Width; 106 UINT64 Address; 107 UINTN Count; 108 UINT8 *Buffer; 109 110 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 111 Address = VA_ARG (Marker, UINT64); 112 Count = VA_ARG (Marker, UINTN); 113 Buffer = VA_ARG (Marker, UINT8 *); 114 115 return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer); 116 } 117 118 /** 119 Internal function to add memory read/write opcode to the table. BootScriptMemReadWrite(IN VA_LIST Marker)120 121 @param Marker The variable argument list to get the opcode 122 and associated attributes. 123 124 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 125 @retval EFI_SUCCESS Opcode is added. 126 127 **/ 128 EFI_STATUS 129 BootScriptMemReadWrite ( 130 IN VA_LIST Marker 131 ) 132 { 133 S3_BOOT_SCRIPT_LIB_WIDTH Width; 134 UINT64 Address; 135 UINT8 *Data; 136 UINT8 *DataMask; 137 138 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 139 Address = VA_ARG (Marker, UINT64); 140 Data = VA_ARG (Marker, UINT8 *); 141 DataMask = VA_ARG (Marker, UINT8 *); 142 143 return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask); 144 } 145 146 /** 147 Internal function to add PciCfg write opcode to the table. BootScriptPciCfgWrite(IN VA_LIST Marker)148 149 @param Marker The variable argument list to get the opcode 150 and associated attributes. 151 152 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 153 @retval EFI_SUCCESS Opcode is added. 154 155 **/ 156 EFI_STATUS 157 BootScriptPciCfgWrite ( 158 IN VA_LIST Marker 159 ) 160 { 161 S3_BOOT_SCRIPT_LIB_WIDTH Width; 162 UINT64 Address; 163 UINTN Count; 164 UINT8 *Buffer; 165 166 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 167 Address = VA_ARG (Marker, UINT64); 168 Count = VA_ARG (Marker, UINTN); 169 Buffer = VA_ARG (Marker, UINT8 *); 170 171 return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer); 172 } 173 174 /** 175 Internal function to PciCfg read/write opcode to the table. BootScriptPciCfgReadWrite(IN VA_LIST Marker)176 177 @param Marker The variable argument list to get the opcode 178 and associated attributes. 179 180 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 181 @retval EFI_SUCCESS Opcode is added. 182 183 **/ 184 EFI_STATUS 185 BootScriptPciCfgReadWrite ( 186 IN VA_LIST Marker 187 ) 188 { 189 S3_BOOT_SCRIPT_LIB_WIDTH Width; 190 UINT64 Address; 191 UINT8 *Data; 192 UINT8 *DataMask; 193 194 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 195 Address = VA_ARG (Marker, UINT64); 196 Data = VA_ARG (Marker, UINT8 *); 197 DataMask = VA_ARG (Marker, UINT8 *); 198 199 return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask); 200 } 201 202 /** 203 Internal function to add PciCfg2 write opcode to the table. BootScriptPciCfg2Write(IN VA_LIST Marker)204 205 @param Marker The variable argument list to get the opcode 206 and associated attributes. 207 208 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 209 @retval EFI_SUCCESS Opcode is added. 210 211 **/ 212 EFI_STATUS 213 BootScriptPciCfg2Write ( 214 IN VA_LIST Marker 215 ) 216 { 217 S3_BOOT_SCRIPT_LIB_WIDTH Width; 218 UINT64 Address; 219 UINTN Count; 220 UINT8 *Buffer; 221 UINT16 Segment; 222 223 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 224 Address = VA_ARG (Marker, UINT64); 225 Count = VA_ARG (Marker, UINTN); 226 Buffer = VA_ARG (Marker, UINT8 *); 227 Segment = VA_ARG (Marker, UINT16); 228 229 return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer); 230 } 231 232 /** 233 Internal function to PciCfg2 read/write opcode to the table. BootScriptPciCfg2ReadWrite(IN VA_LIST Marker)234 235 @param Marker The variable argument list to get the opcode 236 and associated attributes. 237 238 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 239 @retval EFI_SUCCESS Opcode is added. 240 241 **/ 242 EFI_STATUS 243 BootScriptPciCfg2ReadWrite ( 244 IN VA_LIST Marker 245 ) 246 { 247 S3_BOOT_SCRIPT_LIB_WIDTH Width; 248 UINT16 Segment; 249 UINT64 Address; 250 UINT8 *Data; 251 UINT8 *DataMask; 252 253 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 254 Address = VA_ARG (Marker, UINT64); 255 Segment = VA_ARG (Marker, UINT16); 256 Data = VA_ARG (Marker, UINT8 *); 257 DataMask = VA_ARG (Marker, UINT8 *); 258 259 return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask); 260 } 261 262 /** 263 Internal function to add smbus excute opcode to the table. BootScriptSmbusExecute(IN VA_LIST Marker)264 265 @param Marker The variable argument list to get the opcode 266 and associated attributes. 267 268 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 269 @retval EFI_SUCCESS Opcode is added. 270 271 **/ 272 EFI_STATUS 273 BootScriptSmbusExecute ( 274 IN VA_LIST Marker 275 ) 276 { 277 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; 278 EFI_SMBUS_DEVICE_COMMAND Command; 279 EFI_SMBUS_OPERATION Operation; 280 BOOLEAN PecCheck; 281 VOID *Buffer; 282 UINTN *DataSize; 283 UINTN SmBusAddress; 284 285 SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN); 286 Command = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND); 287 Operation = VA_ARG (Marker, EFI_SMBUS_OPERATION); 288 PecCheck = VA_ARG (Marker, BOOLEAN); 289 SmBusAddress = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck); 290 DataSize = VA_ARG (Marker, UINTN *); 291 Buffer = VA_ARG (Marker, VOID *); 292 293 return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer); 294 } 295 296 /** 297 Internal function to add stall opcode to the table. BootScriptStall(IN VA_LIST Marker)298 299 @param Marker The variable argument list to get the opcode 300 and associated attributes. 301 302 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 303 @retval EFI_SUCCESS Opcode is added. 304 305 **/ 306 EFI_STATUS 307 BootScriptStall ( 308 IN VA_LIST Marker 309 ) 310 { 311 UINT32 Duration; 312 313 Duration = VA_ARG (Marker, UINT32); 314 315 return S3BootScriptSaveStall (Duration); 316 } 317 318 /** 319 Internal function to add Save jmp address according to DISPATCH_OPCODE. 320 We ignore "Context" parameter. BootScriptDispatch(IN VA_LIST Marker)321 322 @param Marker The variable argument list to get the opcode 323 and associated attributes. 324 325 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 326 @retval EFI_SUCCESS Opcode is added. 327 328 **/ 329 EFI_STATUS 330 BootScriptDispatch ( 331 IN VA_LIST Marker 332 ) 333 { 334 VOID *EntryPoint; 335 336 EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); 337 return S3BootScriptSaveDispatch (EntryPoint); 338 } 339 340 /** 341 Internal function to add memory pool operation to the table. BootScriptMemPoll(IN VA_LIST Marker)342 343 @param Marker The variable argument list to get the opcode 344 and associated attributes. 345 346 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 347 @retval EFI_SUCCESS Opcode is added. 348 349 **/ 350 EFI_STATUS 351 BootScriptMemPoll ( 352 IN VA_LIST Marker 353 ) 354 { 355 S3_BOOT_SCRIPT_LIB_WIDTH Width; 356 UINT64 Address; 357 UINT8 *BitMask; 358 UINT8 *BitValue; 359 UINTN Duration; 360 UINTN LoopTimes; 361 362 Width = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH); 363 Address = VA_ARG (Marker, UINT64); 364 BitMask = VA_ARG (Marker, UINT8 *); 365 BitValue = VA_ARG (Marker, UINT8 *); 366 Duration = (UINTN)VA_ARG (Marker, UINT64); 367 LoopTimes = (UINTN)VA_ARG (Marker, UINT64); 368 369 return S3BootScriptSaveMemPoll (Width, Address, BitMask, BitValue, Duration, LoopTimes); 370 } 371 372 /** 373 Internal function to add Save jmp address according to DISPATCH_OPCODE2. 374 The "Context" parameter is not ignored. BootScriptDispatch2(IN VA_LIST Marker)375 376 @param Marker The variable argument list to get the opcode 377 and associated attributes. 378 379 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation. 380 @retval EFI_SUCCESS Opcode is added. 381 382 **/ 383 EFI_STATUS 384 BootScriptDispatch2 ( 385 IN VA_LIST Marker 386 ) 387 { 388 VOID *EntryPoint; 389 VOID *Context; 390 391 EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); 392 Context = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); 393 394 return S3BootScriptSaveDispatch2 (EntryPoint, Context); 395 } 396 397 /** 398 Internal function to add the opcode link node to the link list. BootScriptInformation(IN VA_LIST Marker)399 400 @param Marker The variable argument list to get the opcode 401 and associated attributes. 402 403 @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations. 404 @retval EFI_SUCCESS The opcode entry is added to the link list 405 successfully. 406 **/ 407 EFI_STATUS 408 BootScriptInformation ( 409 IN VA_LIST Marker 410 ) 411 { 412 UINT32 InformationLength; 413 EFI_PHYSICAL_ADDRESS Information; 414 415 InformationLength = VA_ARG (Marker, UINT32); 416 Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS); 417 return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information); 418 } 419 420 /** 421 Adds a record into a specified Framework boot script table. 422 423 This function is used to store a boot script record into a given boot 424 script table. If the table specified by TableName is nonexistent in the 425 system, a new table will automatically be created and then the script record 426 will be added into the new table. A boot script table can add new script records 427 until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only 428 meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is 429 responsible for allocating necessary memory for the script. 430 431 This function has a variable parameter list. The exact parameter list depends on 432 the OpCode that is passed into the function. If an unsupported OpCode or illegal 433 parameter list is passed in, this function returns EFI_INVALID_PARAMETER. 434 If there are not enough resources available for storing more scripts, this function returns 435 EFI_OUT_OF_RESOURCES. 436 437 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. 438 @param TableName Name of the script table. Currently, the only meaningful value is 439 EFI_ACPI_S3_RESUME_SCRIPT_TABLE. 440 @param OpCode The operation code (opcode) number. 441 @param ... Argument list that is specific to each opcode. 442 443 @retval EFI_SUCCESS The operation succeeded. A record was added into the BootScriptWrite(IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL * This,IN UINT16 TableName,IN UINT16 OpCode,...)444 specified script table. 445 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. 446 If the opcode is unknow or not supported because of the PCD 447 Feature Flags. 448 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. 449 450 **/ 451 EFI_STATUS 452 EFIAPI 453 BootScriptWrite ( 454 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, 455 IN UINT16 TableName, 456 IN UINT16 OpCode, 457 ... 458 ) 459 { 460 EFI_STATUS Status; 461 VA_LIST Marker; 462 463 if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) { 464 // 465 // Only S3 boot script is supported for now. 466 // 467 return EFI_OUT_OF_RESOURCES; 468 } 469 470 // 471 // Build script according to opcode. 472 // 473 switch (OpCode) { 474 475 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: 476 VA_START (Marker, OpCode); 477 Status = BootScriptIoWrite (Marker); 478 VA_END (Marker); 479 break; 480 481 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE: 482 VA_START (Marker, OpCode); 483 Status = BootScriptIoReadWrite (Marker); 484 VA_END (Marker); 485 break; 486 487 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE: 488 VA_START (Marker, OpCode); 489 Status = BootScriptMemWrite (Marker); 490 VA_END (Marker); 491 break; 492 493 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE: 494 VA_START (Marker, OpCode); 495 Status = BootScriptMemReadWrite (Marker); 496 VA_END (Marker); 497 break; 498 499 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE: 500 VA_START (Marker, OpCode); 501 Status = BootScriptPciCfgWrite (Marker); 502 VA_END (Marker); 503 break; 504 505 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE: 506 VA_START (Marker, OpCode); 507 Status = BootScriptPciCfgReadWrite (Marker); 508 VA_END (Marker); 509 break; 510 511 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE: 512 VA_START (Marker, OpCode); 513 Status = BootScriptSmbusExecute (Marker); 514 VA_END (Marker); 515 break; 516 517 case EFI_BOOT_SCRIPT_STALL_OPCODE: 518 VA_START (Marker, OpCode); 519 Status = BootScriptStall (Marker); 520 VA_END (Marker); 521 522 break; 523 524 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE: 525 VA_START (Marker, OpCode); 526 Status = BootScriptDispatch (Marker); 527 VA_END (Marker); 528 break; 529 530 case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE: 531 VA_START (Marker, OpCode); 532 Status = BootScriptDispatch2 (Marker); 533 VA_END (Marker); 534 break; 535 536 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE: 537 VA_START (Marker, OpCode); 538 Status = BootScriptInformation (Marker); 539 VA_END (Marker); 540 break; 541 542 case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE: 543 VA_START (Marker, OpCode); 544 Status = BootScriptMemPoll (Marker); 545 VA_END (Marker); 546 break; 547 548 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE: 549 VA_START (Marker, OpCode); 550 Status = BootScriptPciCfg2Write (Marker); 551 VA_END (Marker); 552 break; 553 554 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE: 555 VA_START (Marker, OpCode); 556 Status = BootScriptPciCfg2ReadWrite (Marker); 557 VA_END (Marker); 558 break; 559 560 default: 561 Status = EFI_INVALID_PARAMETER; 562 break; 563 } 564 565 return Status; 566 } 567 568 /** 569 Closes the specified script table. 570 571 This function closes the specified boot script table and returns the base address 572 of the table. It allocates a new pool to duplicate all the boot scripts in the specified 573 table. Once this function is called, the specified table will be destroyed after it is 574 copied into the allocated pool. As a result, any attempts to add a script record into a 575 closed table will cause a new table to be created. The base address of the allocated pool 576 will be returned in Address. After using the boot script table, the caller is responsible 577 for freeing the pool that is allocated by this function. If the boot script table, 578 such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed 579 memory region, the caller should copy the table into the nonperturbed memory region by itself. 580 581 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. 582 @param TableName Name of the script table. Currently, the only meaningful value is 583 EFI_ACPI_S3_RESUME_SCRIPT_TABLE. 584 @param Address A pointer to the physical address where the table begins. BootScriptCloseTable(IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL * This,IN UINT16 TableName,OUT EFI_PHYSICAL_ADDRESS * Address)585 586 @retval EFI_SUCCESS The table was successfully returned. 587 @retval EFI_NOT_FOUND The specified table was not created previously. 588 @retval EFI_OUT_OF_RESOURCE Memory is insufficient to hold the reorganized boot script table. 589 @retval EFI_UNSUPPORTED The table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE. 590 591 **/ 592 EFI_STATUS 593 EFIAPI 594 BootScriptCloseTable ( 595 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, 596 IN UINT16 TableName, 597 OUT EFI_PHYSICAL_ADDRESS *Address 598 ) 599 { 600 if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) { 601 // 602 // Only S3 boot script is supported for now. 603 // 604 return EFI_NOT_FOUND; 605 } 606 *Address = (EFI_PHYSICAL_ADDRESS)(UINTN)S3BootScriptCloseTable (); 607 608 if (*Address == 0) { 609 return EFI_NOT_FOUND; 610 } 611 return EFI_SUCCESS; 612 } 613 614 /** 615 This routine is entry point of ScriptSave driver. 616 617 @param ImageHandle Handle for this drivers loaded image protocol. InitializeScriptSave(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)618 @param SystemTable EFI system table. 619 620 @retval EFI_OUT_OF_RESOURCES No enough resource. 621 @retval EFI_SUCCESS Succesfully installed the ScriptSave driver. 622 @retval other Errors occured. 623 624 **/ 625 EFI_STATUS 626 EFIAPI 627 InitializeScriptSave ( 628 IN EFI_HANDLE ImageHandle, 629 IN EFI_SYSTEM_TABLE *SystemTable 630 ) 631 { 632 return gBS->InstallProtocolInterface ( 633 &mHandle, 634 &gEfiBootScriptSaveProtocolGuid, 635 EFI_NATIVE_INTERFACE, 636 &mS3ScriptSave 637 ); 638 639 } 640 641