]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/ScriptSave.c
Update module to pass in a valid EFI_HANDLE when is reloads and restarts itself using...
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / BootScriptSaveOnS3SaveStateThunk / ScriptSave.c
1 /** @file
2 Implementation for S3 Boot Script Save thunk driver.
3 This thunk driver consumes PI S3SaveState protocol to produce framework S3BootScriptSave Protocol
4
5 Copyright (c) 2010 - 2011, 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 #include "ScriptSave.h"
16
17 EFI_HANDLE mHandle;
18 EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave = {
19 BootScriptWrite,
20 BootScriptCloseTable
21 };
22 EFI_S3_SAVE_STATE_PROTOCOL *mS3SaveState;
23
24 /**
25 Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
26 long mode.
27
28 @param Function The 32bit code entry to be executed.
29 @param Param1 The first parameter to pass to 32bit code
30 @param Param2 The second parameter to pass to 32bit code
31 @retval EFI_SUCCESS Execute 32bit code successfully.
32 @retval other Something wrong when execute the 32bit code
33
34 **/
35 EFI_STATUS
36 Execute32BitCode (
37 IN UINT64 Function,
38 IN UINT64 Param1,
39 IN UINT64 Param2
40 );
41
42 /**
43 A stub to convert framework boot script dispatch to PI boot script dispatch.
44
45 @param ImageHandle It should be is NULL.
46 @param Context The first parameter to pass to 32bit code
47
48 @return dispatch value.
49
50 **/
51 EFI_STATUS
52 EFIAPI
53 FrameworkBootScriptDispatchStub (
54 IN EFI_HANDLE ImageHandle,
55 IN VOID *Context
56 )
57 {
58 EFI_STATUS Status;
59 DISPATCH_ENTRYPOINT_FUNC EntryFunc;
60 VOID *PeiServices;
61 IA32_DESCRIPTOR Idtr;
62
63 DEBUG ((EFI_D_ERROR, "FrameworkBootScriptDispatchStub - 0x%08x\n", (UINTN)Context));
64
65 EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (Context);
66 AsmReadIdtr (&Idtr);
67 PeiServices = (VOID *)(UINTN)(*(UINT32 *)(Idtr.Base - sizeof (UINT32)));
68
69 //
70 // ECP assumes first parameter is NULL, and second parameter is PeiServices.
71 //
72 Status = Execute32BitCode ((UINT64)(UINTN)EntryFunc, 0, (UINT64)(UINTN)PeiServices);
73
74 return Status;
75 }
76
77 /**
78 Internal function to add IO write opcode to the table.
79
80 @param Marker The variable argument list to get the opcode
81 and associated attributes.
82
83 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
84 @retval EFI_SUCCESS Opcode is added.
85
86 **/
87 EFI_STATUS
88 BootScriptIoWrite (
89 IN VA_LIST Marker
90 )
91 {
92 EFI_BOOT_SCRIPT_WIDTH Width;
93 UINT64 Address;
94 UINTN Count;
95 UINT8 *Buffer;
96
97 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
98 Address = VA_ARG (Marker, UINT64);
99 Count = VA_ARG (Marker, UINTN);
100 Buffer = VA_ARG (Marker, UINT8 *);
101
102 return mS3SaveState->Write (
103 mS3SaveState,
104 EFI_BOOT_SCRIPT_IO_WRITE_OPCODE,
105 Width,
106 Address,
107 Count,
108 Buffer
109 );
110 }
111 /**
112 Internal function to add IO read/write opcode to the table.
113
114 @param Marker The variable argument list to get the opcode
115 and associated attributes.
116
117 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
118 @retval EFI_SUCCESS Opcode is added.
119
120 **/
121 EFI_STATUS
122 BootScriptIoReadWrite (
123 IN VA_LIST Marker
124 )
125 {
126 EFI_BOOT_SCRIPT_WIDTH Width;
127 UINT64 Address;
128 UINT8 *Data;
129 UINT8 *DataMask;
130
131 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
132 Address = VA_ARG (Marker, UINT64);
133 Data = VA_ARG (Marker, UINT8 *);
134 DataMask = VA_ARG (Marker, UINT8 *);
135
136 return mS3SaveState->Write (
137 mS3SaveState,
138 EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE,
139 Width,
140 Address,
141 Data,
142 DataMask
143 );
144 }
145
146 /**
147 Internal function to add memory write opcode to the table.
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 BootScriptMemWrite (
158 IN VA_LIST Marker
159 )
160 {
161 EFI_BOOT_SCRIPT_WIDTH Width;
162 UINT64 Address;
163 UINTN Count;
164 UINT8 *Buffer;
165
166 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
167 Address = VA_ARG (Marker, UINT64);
168 Count = VA_ARG (Marker, UINTN);
169 Buffer = VA_ARG (Marker, UINT8 *);
170
171 return mS3SaveState->Write (
172 mS3SaveState,
173 EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE,
174 Width,
175 Address,
176 Count,
177 Buffer
178 );
179 }
180
181 /**
182 Internal function to add memory read/write opcode to the table.
183
184 @param Marker The variable argument list to get the opcode
185 and associated attributes.
186
187 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
188 @retval EFI_SUCCESS Opcode is added.
189
190 **/
191 EFI_STATUS
192 BootScriptMemReadWrite (
193 IN VA_LIST Marker
194 )
195 {
196 EFI_BOOT_SCRIPT_WIDTH Width;
197 UINT64 Address;
198 UINT8 *Data;
199 UINT8 *DataMask;
200
201 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
202 Address = VA_ARG (Marker, UINT64);
203 Data = VA_ARG (Marker, UINT8 *);
204 DataMask = VA_ARG (Marker, UINT8 *);
205
206 return mS3SaveState->Write (
207 mS3SaveState,
208 EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE,
209 Width,
210 Address,
211 Data,
212 DataMask
213 );
214 }
215
216 /**
217 Internal function to add PciCfg write opcode to the table.
218
219 @param Marker The variable argument list to get the opcode
220 and associated attributes.
221
222 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
223 @retval EFI_SUCCESS Opcode is added.
224
225 **/
226 EFI_STATUS
227 BootScriptPciCfgWrite (
228 IN VA_LIST Marker
229 )
230 {
231 EFI_BOOT_SCRIPT_WIDTH Width;
232 UINT64 Address;
233 UINTN Count;
234 UINT8 *Buffer;
235
236 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
237 Address = VA_ARG (Marker, UINT64);
238 Count = VA_ARG (Marker, UINTN);
239 Buffer = VA_ARG (Marker, UINT8 *);
240
241 return mS3SaveState->Write (
242 mS3SaveState,
243 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE,
244 Width,
245 Address,
246 Count,
247 Buffer
248 );
249 }
250
251 /**
252 Internal function to PciCfg read/write opcode to the table.
253
254 @param Marker The variable argument list to get the opcode
255 and associated attributes.
256
257 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
258 @retval EFI_SUCCESS Opcode is added.
259
260 **/
261 EFI_STATUS
262 BootScriptPciCfgReadWrite (
263 IN VA_LIST Marker
264 )
265 {
266 EFI_BOOT_SCRIPT_WIDTH Width;
267 UINT64 Address;
268 UINT8 *Data;
269 UINT8 *DataMask;
270
271 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
272 Address = VA_ARG (Marker, UINT64);
273 Data = VA_ARG (Marker, UINT8 *);
274 DataMask = VA_ARG (Marker, UINT8 *);
275
276 return mS3SaveState->Write (
277 mS3SaveState,
278 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE,
279 Width,
280 Address,
281 Data,
282 DataMask
283 );
284 }
285 /**
286 Internal function to add PciCfg2 write opcode to the table.
287
288 @param Marker The variable argument list to get the opcode
289 and associated attributes.
290
291 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
292 @retval EFI_SUCCESS Opcode is added.
293
294 **/
295 EFI_STATUS
296 BootScriptPciCfg2Write (
297 IN VA_LIST Marker
298 )
299 {
300 EFI_BOOT_SCRIPT_WIDTH Width;
301 UINT64 Address;
302 UINTN Count;
303 UINT8 *Buffer;
304 UINT16 Segment;
305
306 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
307 Address = VA_ARG (Marker, UINT64);
308 Count = VA_ARG (Marker, UINTN);
309 Buffer = VA_ARG (Marker, UINT8 *);
310 Segment = VA_ARG (Marker, UINT16);
311
312 return mS3SaveState->Write (
313 mS3SaveState,
314 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE,
315 Width,
316 Segment,
317 Address,
318 Count,
319 Buffer
320 );
321 }
322
323 /**
324 Internal function to PciCfg2 read/write opcode to the table.
325
326 @param Marker The variable argument list to get the opcode
327 and associated attributes.
328
329 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
330 @retval EFI_SUCCESS Opcode is added.
331
332 **/
333 EFI_STATUS
334 BootScriptPciCfg2ReadWrite (
335 IN VA_LIST Marker
336 )
337 {
338 EFI_BOOT_SCRIPT_WIDTH Width;
339 UINT16 Segment;
340 UINT64 Address;
341 UINT8 *Data;
342 UINT8 *DataMask;
343
344 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
345 Address = VA_ARG (Marker, UINT64);
346 Segment = VA_ARG (Marker, UINT16);
347 Data = VA_ARG (Marker, UINT8 *);
348 DataMask = VA_ARG (Marker, UINT8 *);
349
350 return mS3SaveState->Write (
351 mS3SaveState,
352 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE,
353 Width,
354 Segment,
355 Address,
356 Data,
357 DataMask
358 );
359 }
360 /**
361 Internal function to add smbus excute opcode to the table.
362
363 @param Marker The variable argument list to get the opcode
364 and associated attributes.
365
366 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
367 @retval EFI_SUCCESS Opcode is added.
368
369 **/
370 EFI_STATUS
371 BootScriptSmbusExecute (
372 IN VA_LIST Marker
373 )
374 {
375 EFI_SMBUS_DEVICE_ADDRESS SlaveAddress;
376 EFI_SMBUS_DEVICE_COMMAND Command;
377 EFI_SMBUS_OPERATION Operation;
378 BOOLEAN PecCheck;
379 VOID *Buffer;
380 UINTN *DataSize;
381
382 SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
383 Command = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
384 Operation = VA_ARG (Marker, EFI_SMBUS_OPERATION);
385 PecCheck = VA_ARG (Marker, BOOLEAN);
386 DataSize = VA_ARG (Marker, UINTN *);
387 Buffer = VA_ARG (Marker, VOID *);
388
389 return mS3SaveState->Write (
390 mS3SaveState,
391 EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE,
392 SlaveAddress,
393 Command,
394 Operation,
395 PecCheck,
396 DataSize,
397 Buffer
398 );
399 }
400 /**
401 Internal function to add stall opcode to the table.
402
403 @param Marker The variable argument list to get the opcode
404 and associated attributes.
405
406 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
407 @retval EFI_SUCCESS Opcode is added.
408
409 **/
410 EFI_STATUS
411 BootScriptStall (
412 IN VA_LIST Marker
413 )
414 {
415 UINT32 Duration;
416
417 Duration = VA_ARG (Marker, UINT32);
418
419 return mS3SaveState->Write (
420 mS3SaveState,
421 EFI_BOOT_SCRIPT_STALL_OPCODE,
422 Duration
423 );
424 }
425
426 /**
427 Internal function to add Save jmp address according to DISPATCH_OPCODE.
428 We ignore "Context" parameter
429
430 @param Marker The variable argument list to get the opcode
431 and associated attributes.
432
433 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
434 @retval EFI_SUCCESS Opcode is added.
435
436 **/
437 EFI_STATUS
438 BootScriptDispatch (
439 IN VA_LIST Marker
440 )
441 {
442 VOID *EntryPoint;
443
444 EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
445 return mS3SaveState->Write (
446 mS3SaveState,
447 EFI_BOOT_SCRIPT_DISPATCH_OPCODE,
448 EntryPoint
449 );
450 }
451
452 /**
453 Internal function to add Save jmp address according to DISPATCH_OPCODE.
454 We ignore "Context" parameter.
455 We need create thunk stub to convert PEI entrypoint (used in Framework version)
456 to DXE entrypoint (defined in PI spec).
457
458 @param Marker The variable argument list to get the opcode
459 and associated attributes.
460
461 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
462 @retval EFI_SUCCESS Opcode is added.
463
464 **/
465 EFI_STATUS
466 FrameworkBootScriptDispatch (
467 IN VA_LIST Marker
468 )
469 {
470 VOID *EntryPoint;
471 VOID *Context;
472
473 EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
474
475 //
476 // Register callback
477 //
478 Context = EntryPoint;
479 EntryPoint = (VOID *)(UINTN)FrameworkBootScriptDispatchStub;
480 return mS3SaveState->Write (
481 mS3SaveState,
482 EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,
483 EntryPoint,
484 Context
485 );
486 }
487
488 /**
489 Internal function to add memory pool operation to the table.
490
491 @param Marker The variable argument list to get the opcode
492 and associated attributes.
493
494 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
495 @retval EFI_SUCCESS Opcode is added.
496
497 **/
498 EFI_STATUS
499 BootScriptMemPoll (
500 IN VA_LIST Marker
501 )
502 {
503 EFI_BOOT_SCRIPT_WIDTH Width;
504 UINT64 Address;
505 UINT8 *BitMask;
506 UINT8 *BitValue;
507 UINT64 Duration;
508 UINT64 LoopTimes;
509 UINT64 Delay;
510
511 Width = VA_ARG (Marker, EFI_BOOT_SCRIPT_WIDTH);
512 Address = VA_ARG (Marker, UINT64);
513 BitMask = VA_ARG (Marker, UINT8 *);
514 BitValue = VA_ARG (Marker, UINT8 *);
515 Duration = (UINT64)VA_ARG (Marker, UINT64);
516 LoopTimes = (UINT64)VA_ARG (Marker, UINT64);
517 Delay = MultU64x64 (DivU64x32(Duration, 100), LoopTimes);
518
519 return mS3SaveState->Write (
520 mS3SaveState,
521 EFI_BOOT_SCRIPT_MEM_POLL_OPCODE,
522 Width,
523 Address,
524 BitMask,
525 BitValue,
526 Delay
527 );
528 }
529
530 /**
531 Internal function to add Save jmp address according to DISPATCH_OPCODE2.
532 The "Context" parameter is not ignored.
533
534 @param Marker The variable argument list to get the opcode
535 and associated attributes.
536
537 @retval EFI_OUT_OF_RESOURCES Not enough resource to do operation.
538 @retval EFI_SUCCESS Opcode is added.
539
540 **/
541 EFI_STATUS
542 BootScriptDispatch2 (
543 IN VA_LIST Marker
544 )
545 {
546 VOID *EntryPoint;
547 VOID *Context;
548
549 EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
550 Context = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
551
552 return mS3SaveState->Write (
553 mS3SaveState,
554 EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,
555 EntryPoint,
556 Context
557 );
558 }
559 /**
560 Internal function to add the opcode link node to the link
561 list.
562 @param Marker The variable argument list to get the opcode
563 and associated attributes.
564
565 @retval EFI_OUT_OF_RESOURCES Not enought resource to complete the operations.
566 @retval EFI_SUCCESS The opcode entry is added to the link list
567 successfully.
568 **/
569 EFI_STATUS
570 BootScriptInformation (
571 IN VA_LIST Marker
572 )
573 {
574 UINT32 InformationLength;
575 EFI_PHYSICAL_ADDRESS Information;
576
577 InformationLength = VA_ARG (Marker, UINT32);
578 Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
579
580 return mS3SaveState->Write (
581 mS3SaveState,
582 EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
583 InformationLength,
584 (VOID*)(UINTN)Information
585 );
586 }
587
588 /**
589 Adds a record into a specified Framework boot script table.
590
591 This function is used to store a boot script record into a given boot
592 script table. If the table specified by TableName is nonexistent in the
593 system, a new table will automatically be created and then the script record
594 will be added into the new table. A boot script table can add new script records
595 until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only
596 meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is
597 responsible for allocating necessary memory for the script.
598
599 This function has a variable parameter list. The exact parameter list depends on
600 the OpCode that is passed into the function. If an unsupported OpCode or illegal
601 parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
602 If there are not enough resources available for storing more scripts, this function returns
603 EFI_OUT_OF_RESOURCES.
604
605 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
606 @param TableName Name of the script table. Currently, the only meaningful value is
607 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
608 @param OpCode The operation code (opcode) number.
609 @param ... Argument list that is specific to each opcode.
610
611 @retval EFI_SUCCESS The operation succeeded. A record was added into the
612 specified script table.
613 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
614 If the opcode is unknow or not supported because of the PCD
615 Feature Flags.
616 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
617
618 **/
619 EFI_STATUS
620 EFIAPI
621 BootScriptWrite (
622 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This,
623 IN UINT16 TableName,
624 IN UINT16 OpCode,
625 ...
626 )
627 {
628 EFI_STATUS Status;
629 VA_LIST Marker;
630
631 if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
632 //
633 // Only S3 boot script is supported for now
634 //
635 return EFI_OUT_OF_RESOURCES;
636 }
637 //
638 // Build script according to opcode
639 //
640 switch (OpCode) {
641
642 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
643 VA_START (Marker, OpCode);
644 Status = BootScriptIoWrite (Marker);
645 VA_END (Marker);
646 break;
647
648 case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
649 VA_START (Marker, OpCode);
650 Status = BootScriptIoReadWrite (Marker);
651 VA_END (Marker);
652 break;
653
654 case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
655 VA_START (Marker, OpCode);
656 Status = BootScriptMemWrite (Marker);
657 VA_END (Marker);
658 break;
659
660 case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
661 VA_START (Marker, OpCode);
662 Status = BootScriptMemReadWrite (Marker);
663 VA_END (Marker);
664 break;
665
666 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
667 VA_START (Marker, OpCode);
668 Status = BootScriptPciCfgWrite (Marker);
669 VA_END (Marker);
670 break;
671
672 case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
673 VA_START (Marker, OpCode);
674 Status = BootScriptPciCfgReadWrite (Marker);
675 VA_END (Marker);
676 break;
677
678 case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
679 VA_START (Marker, OpCode);
680 Status = BootScriptSmbusExecute (Marker);
681 VA_END (Marker);
682 break;
683
684 case EFI_BOOT_SCRIPT_STALL_OPCODE:
685 VA_START (Marker, OpCode);
686 Status = BootScriptStall (Marker);
687 VA_END (Marker);
688
689 break;
690
691 case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
692 VA_START (Marker, OpCode);
693 Status = FrameworkBootScriptDispatch (Marker);
694 VA_END (Marker);
695 break;
696
697 case FRAMEWORK_EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
698 VA_START (Marker, OpCode);
699 Status = BootScriptDispatch2 (Marker);
700 VA_END (Marker);
701 break;
702
703 case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
704 VA_START (Marker, OpCode);
705 Status = BootScriptInformation (Marker);
706 VA_END (Marker);
707 break;
708
709 case FRAMEWORK_EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
710 VA_START (Marker, OpCode);
711 Status = BootScriptMemPoll (Marker);
712 VA_END (Marker);
713 break;
714
715 case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
716 VA_START (Marker, OpCode);
717 Status = BootScriptPciCfg2Write (Marker);
718 VA_END (Marker);
719 break;
720
721 case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
722 VA_START (Marker, OpCode);
723 Status = BootScriptPciCfg2ReadWrite (Marker);
724 VA_END (Marker);
725 break;
726
727 default:
728 Status = EFI_INVALID_PARAMETER;
729 break;
730 }
731
732 return Status;
733 }
734
735 /**
736 Closes the specified script table.
737
738 This function closes the specified boot script table and returns the base address
739 of the table. It allocates a new pool to duplicate all the boot scripts in the specified
740 table. Once this function is called, the specified table will be destroyed after it is
741 copied into the allocated pool. As a result, any attempts to add a script record into a
742 closed table will cause a new table to be created. The base address of the allocated pool
743 will be returned in Address. After using the boot script table, the caller is responsible
744 for freeing the pool that is allocated by this function. If the boot script table,
745 such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed
746 memory region, the caller should copy the table into the nonperturbed memory region by itself.
747
748 @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
749 @param TableName Name of the script table. Currently, the only meaningful value is
750 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
751 @param Address A pointer to the physical address where the table begins.
752
753 @retval EFI_SUCCESS The table was successfully returned.
754 @retval EFI_NOT_FOUND The specified table was not created previously.
755 @retval EFI_OUT_OF_RESOURCE Memory is insufficient to hold the reorganized boot script table.
756 @retval EFI_UNSUPPORTED the table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE
757
758 **/
759 EFI_STATUS
760 EFIAPI
761 BootScriptCloseTable (
762 IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This,
763 IN UINT16 TableName,
764 OUT EFI_PHYSICAL_ADDRESS *Address
765 )
766 {
767 if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
768 //
769 // Only S3 boot script is supported for now
770 //
771 return EFI_NOT_FOUND;
772 }
773 //
774 // Here the close table is not implemented.
775 //
776
777 return EFI_UNSUPPORTED;
778 }
779
780 /**
781 This routine is entry point of ScriptSave driver.
782
783 @param ImageHandle Handle for this drivers loaded image protocol.
784 @param SystemTable EFI system table.
785
786 @retval EFI_OUT_OF_RESOURCES No enough resource
787 @retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
788 @retval other Errors occured.
789
790 **/
791 EFI_STATUS
792 EFIAPI
793 InitializeScriptSaveOnS3SaveState (
794 IN EFI_HANDLE ImageHandle,
795 IN EFI_SYSTEM_TABLE *SystemTable
796 )
797 {
798 UINT8 *Buffer;
799 UINTN BufferSize;
800 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
801 BOOT_SCRIPT_THUNK_DATA *BootScriptThunkData;
802 EFI_STATUS Status;
803 VOID *DevicePath;
804 EFI_PHYSICAL_ADDRESS MemoryAddress;
805 UINTN PageNumber;
806 EFI_HANDLE NewImageHandle;
807
808 //
809 // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
810 // point is loaded by DXE code which is the first time loaded. or else, it is already
811 // be reloaded be itself.This is a work-around
812 //
813 Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
814 if (EFI_ERROR (Status)) {
815 //
816 // This is the first-time loaded by DXE core. reload itself to NVS mem
817 //
818 //
819 // A workarouond: Here we install a dummy handle
820 //
821 NewImageHandle = NULL;
822 Status = gBS->InstallProtocolInterface (
823 &NewImageHandle,
824 &gEfiCallerIdGuid,
825 EFI_NATIVE_INTERFACE,
826 NULL
827 );
828
829 Status = GetSectionFromAnyFv (
830 &gEfiCallerIdGuid,
831 EFI_SECTION_PE32,
832 0,
833 (VOID **) &Buffer,
834 &BufferSize
835 );
836 ImageContext.Handle = Buffer;
837 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
838 //
839 // Get information about the image being loaded
840 //
841 Status = PeCoffLoaderGetImageInfo (&ImageContext);
842 if (EFI_ERROR (Status)) {
843 return Status;
844 }
845
846 MemoryAddress = SIZE_4GB - 1;
847 PageNumber = EFI_SIZE_TO_PAGES (BufferSize + ImageContext.SectionAlignment);
848 Status = gBS->AllocatePages (
849 AllocateMaxAddress,
850 EfiACPIMemoryNVS,
851 PageNumber,
852 &MemoryAddress
853 );
854 if (EFI_ERROR (Status)) {
855 return EFI_OUT_OF_RESOURCES;
856 }
857 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
858 //
859 // Align buffer on section boundry
860 //
861 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
862 ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
863 //
864 // Load the image to our new buffer
865 //
866 Status = PeCoffLoaderLoadImage (&ImageContext);
867 if (EFI_ERROR (Status)) {
868 gBS->FreePages (MemoryAddress, PageNumber);
869 return Status;
870 }
871
872 //
873 // Relocate the image in our new buffer
874 //
875 Status = PeCoffLoaderRelocateImage (&ImageContext);
876
877 if (EFI_ERROR (Status)) {
878 PeCoffLoaderUnloadImage (&ImageContext);
879 gBS->FreePages (MemoryAddress, PageNumber);
880 return Status;
881 }
882 //
883 // Flush the instruction cache so the image data is written before we execute it
884 //
885 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
886 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
887 if (EFI_ERROR (Status)) {
888 gBS->FreePages (MemoryAddress, PageNumber);
889 return Status;
890 }
891 //
892 // Additional step for BootScriptThunk integrity
893 //
894
895 //
896 // Allocate BootScriptThunkData
897 //
898 BootScriptThunkData = AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA));
899 if (BootScriptThunkData == NULL) {
900 return EFI_OUT_OF_RESOURCES;
901 }
902
903 BootScriptThunkData->BootScriptThunkBase = ImageContext.ImageAddress;
904 BootScriptThunkData->BootScriptThunkLength = ImageContext.ImageSize;
905 //
906 // Set BootScriptThunkData
907 //
908 PcdSet64 (BootScriptThunkDataPtr, (UINT64)(UINTN)BootScriptThunkData);
909 return EFI_SUCCESS;
910 } else {
911 //
912 // the entry point is invoked after reloading. following code only run in ACPI NVS
913 //
914
915 //
916 // Locate and cache PI S3 Save State Protocol.
917 //
918 Status = gBS->LocateProtocol (
919 &gEfiS3SaveStateProtocolGuid,
920 NULL,
921 (VOID **) &mS3SaveState
922 );
923 ASSERT_EFI_ERROR (Status);
924
925 return gBS->InstallProtocolInterface (
926 &mHandle,
927 &gEfiBootScriptSaveProtocolGuid,
928 EFI_NATIVE_INTERFACE,
929 &mS3ScriptSave
930 );
931 }
932 }
933
934