• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 - 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 #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
FrameworkBootScriptDispatchStub(IN EFI_HANDLE ImageHandle,IN VOID * Context)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
BootScriptIoWrite(IN VA_LIST Marker)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
BootScriptIoReadWrite(IN VA_LIST Marker)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
BootScriptMemWrite(IN VA_LIST Marker)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
BootScriptMemReadWrite(IN VA_LIST Marker)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
BootScriptPciCfgWrite(IN VA_LIST Marker)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
BootScriptPciCfgReadWrite(IN VA_LIST Marker)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
BootScriptPciCfg2Write(IN VA_LIST Marker)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
BootScriptPciCfg2ReadWrite(IN VA_LIST Marker)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
BootScriptSmbusExecute(IN VA_LIST Marker)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
BootScriptStall(IN VA_LIST Marker)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
BootScriptDispatch(IN VA_LIST Marker)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
FrameworkBootScriptDispatch(IN VA_LIST Marker)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
BootScriptMemPoll(IN VA_LIST Marker)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   //
518   // Framework version: Duration is used for Stall(), which is Microseconds.
519   //                    Total time is: Duration(Microseconds) * LoopTimes.
520   // PI version:        Duration is always 100ns. Delay is LoopTimes.
521   //                    Total time is: 100ns * Delay.
522   // So Delay = Duration(Microseconds) * LoopTimes / 100ns
523   //          = Duration * 1000ns * LoopTimes / 100ns
524   //          = Duration * 10 * LoopTimes
525   //
526   Delay       = MultU64x64 (MultU64x32 (Duration, 10), LoopTimes);
527 
528   //
529   // Framework version: First BitMask, then BitValue
530   // PI version: First Data, then DataMask
531   // So we revert their order in function call
532   //
533   return mS3SaveState->Write (
534                           mS3SaveState,
535                           EFI_BOOT_SCRIPT_MEM_POLL_OPCODE,
536                           Width,
537                           Address,
538                           BitValue,
539                           BitMask,
540                           Delay
541                           );
542 }
543 
544 /**
545   Internal function to add Save jmp address according to DISPATCH_OPCODE2.
546   The "Context" parameter is not ignored.
547 
548   @param  Marker                The variable argument list to get the opcode
549                                 and associated attributes.
550 
551   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
552   @retval EFI_SUCCESS           Opcode is added.
553 
554 **/
555 EFI_STATUS
BootScriptDispatch2(IN VA_LIST Marker)556 BootScriptDispatch2 (
557   IN VA_LIST                       Marker
558   )
559 {
560   VOID                  *EntryPoint;
561   VOID                  *Context;
562 
563   EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
564   Context    = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
565 
566  return mS3SaveState->Write (
567                           mS3SaveState,
568                           EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE,
569                           EntryPoint,
570                           Context
571                          );
572 }
573 /**
574   Internal function to add the opcode link node to the link
575   list.
576   @param  Marker                The variable argument list to get the opcode
577                                 and associated attributes.
578 
579   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
580   @retval EFI_SUCCESS           The opcode entry is added to the link list
581                                 successfully.
582 **/
583 EFI_STATUS
BootScriptInformation(IN VA_LIST Marker)584 BootScriptInformation (
585   IN VA_LIST                       Marker
586   )
587 {
588   UINT32                InformationLength;
589   EFI_PHYSICAL_ADDRESS  Information;
590 
591   InformationLength = VA_ARG (Marker, UINT32);
592   Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
593 
594   return mS3SaveState->Write (
595                           mS3SaveState,
596                           EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
597                           InformationLength,
598                           (VOID*)(UINTN)Information
599                          );
600 }
601 
602 /**
603   Adds a record into a specified Framework boot script table.
604 
605   This function is used to store a boot script record into a given boot
606   script table. If the table specified by TableName is nonexistent in the
607   system, a new table will automatically be created and then the script record
608   will be added into the new table. A boot script table can add new script records
609   until EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is called. Currently, the only
610   meaningful table name is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. This function is
611   responsible for allocating necessary memory for the script.
612 
613   This function has a variable parameter list. The exact parameter list depends on
614   the OpCode that is passed into the function. If an unsupported OpCode or illegal
615   parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
616   If there are not enough resources available for storing more scripts, this function returns
617   EFI_OUT_OF_RESOURCES.
618 
619   @param  This                  A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
620   @param  TableName             Name of the script table. Currently, the only meaningful value is
621                                 EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
622   @param  OpCode                The operation code (opcode) number.
623   @param  ...                   Argument list that is specific to each opcode.
624 
625   @retval EFI_SUCCESS           The operation succeeded. A record was added into the
626                                 specified script table.
627   @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
628                                 If the opcode is unknow or not supported because of the PCD
629                                 Feature Flags.
630   @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
631 
632 **/
633 EFI_STATUS
634 EFIAPI
BootScriptWrite(IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL * This,IN UINT16 TableName,IN UINT16 OpCode,...)635 BootScriptWrite (
636   IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL    *This,
637   IN UINT16                           TableName,
638   IN UINT16                           OpCode,
639   ...
640   )
641 {
642   EFI_STATUS                Status;
643   VA_LIST                   Marker;
644 
645   if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
646     //
647     // Only S3 boot script is supported for now
648     //
649     return EFI_OUT_OF_RESOURCES;
650   }
651   //
652   // Build script according to opcode
653   //
654   switch (OpCode) {
655 
656   case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
657     VA_START (Marker, OpCode);
658     Status = BootScriptIoWrite (Marker);
659     VA_END (Marker);
660     break;
661 
662   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
663     VA_START (Marker, OpCode);
664     Status = BootScriptIoReadWrite (Marker);
665     VA_END (Marker);
666     break;
667 
668   case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
669     VA_START (Marker, OpCode);
670     Status = BootScriptMemWrite (Marker);
671     VA_END (Marker);
672     break;
673 
674   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
675     VA_START (Marker, OpCode);
676     Status = BootScriptMemReadWrite (Marker);
677     VA_END (Marker);
678     break;
679 
680   case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
681     VA_START (Marker, OpCode);
682     Status = BootScriptPciCfgWrite (Marker);
683     VA_END (Marker);
684     break;
685 
686   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
687     VA_START (Marker, OpCode);
688     Status = BootScriptPciCfgReadWrite (Marker);
689     VA_END (Marker);
690     break;
691 
692   case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
693     VA_START (Marker, OpCode);
694     Status = BootScriptSmbusExecute (Marker);
695     VA_END (Marker);
696     break;
697 
698   case EFI_BOOT_SCRIPT_STALL_OPCODE:
699     VA_START (Marker, OpCode);
700     Status = BootScriptStall (Marker);
701     VA_END (Marker);
702 
703     break;
704 
705   case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
706     VA_START (Marker, OpCode);
707     Status = FrameworkBootScriptDispatch (Marker);
708     VA_END (Marker);
709     break;
710 
711   case FRAMEWORK_EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
712     VA_START (Marker, OpCode);
713     Status = BootScriptDispatch2 (Marker);
714     VA_END (Marker);
715     break;
716 
717   case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
718     VA_START (Marker, OpCode);
719     Status = BootScriptInformation (Marker);
720     VA_END (Marker);
721     break;
722 
723   case FRAMEWORK_EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
724     VA_START (Marker, OpCode);
725     Status = BootScriptMemPoll (Marker);
726     VA_END (Marker);
727     break;
728 
729   case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
730     VA_START (Marker, OpCode);
731     Status = BootScriptPciCfg2Write (Marker);
732     VA_END (Marker);
733     break;
734 
735   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
736     VA_START (Marker, OpCode);
737     Status = BootScriptPciCfg2ReadWrite (Marker);
738     VA_END (Marker);
739     break;
740 
741   default:
742     Status = EFI_INVALID_PARAMETER;
743     break;
744   }
745 
746   return Status;
747 }
748 
749 /**
750   Closes the specified script table.
751 
752   This function closes the specified boot script table and returns the base address
753   of the table. It allocates a new pool to duplicate all the boot scripts in the specified
754   table. Once this function is called, the specified table will be destroyed after it is
755   copied into the allocated pool. As a result, any attempts to add a script record into a
756   closed table will cause a new table to be created. The base address of the allocated pool
757   will be returned in Address. After using the boot script table, the caller is responsible
758   for freeing the pool that is allocated by this function. If the boot script table,
759   such as EFI_ACPI_S3_RESUME_SCRIPT_TABLE, is required to be stored in a nonperturbed
760   memory region, the caller should copy the table into the nonperturbed memory region by itself.
761 
762   @param  This                  A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance.
763   @param  TableName             Name of the script table. Currently, the only meaningful value is
764                                  EFI_ACPI_S3_RESUME_SCRIPT_TABLE.
765   @param  Address               A pointer to the physical address where the table begins.
766 
767   @retval EFI_SUCCESS           The table was successfully returned.
768   @retval EFI_NOT_FOUND         The specified table was not created previously.
769   @retval EFI_OUT_OF_RESOURCE   Memory is insufficient to hold the reorganized boot script table.
770   @retval EFI_UNSUPPORTED       the table type is not EFI_ACPI_S3_RESUME_SCRIPT_TABLE
771 
772 **/
773 EFI_STATUS
774 EFIAPI
BootScriptCloseTable(IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL * This,IN UINT16 TableName,OUT EFI_PHYSICAL_ADDRESS * Address)775 BootScriptCloseTable (
776   IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL    *This,
777   IN UINT16                           TableName,
778   OUT EFI_PHYSICAL_ADDRESS            *Address
779   )
780 {
781   if (TableName != FRAMEWORK_EFI_ACPI_S3_RESUME_SCRIPT_TABLE) {
782     //
783     // Only S3 boot script is supported for now
784     //
785     return EFI_NOT_FOUND;
786   }
787   //
788   // Here the close table is not implemented.
789   //
790 
791   return EFI_UNSUPPORTED;
792 }
793 
794 /**
795   Register image to memory profile.
796 
797   @param FileName       File name of the image.
798   @param ImageBase      Image base address.
799   @param ImageSize      Image size.
800   @param FileType       File type of the image.
801 
802 **/
803 VOID
RegisterMemoryProfileImage(IN EFI_GUID * FileName,IN PHYSICAL_ADDRESS ImageBase,IN UINT64 ImageSize,IN EFI_FV_FILETYPE FileType)804 RegisterMemoryProfileImage (
805   IN EFI_GUID                       *FileName,
806   IN PHYSICAL_ADDRESS               ImageBase,
807   IN UINT64                         ImageSize,
808   IN EFI_FV_FILETYPE                FileType
809   )
810 {
811   EFI_STATUS                        Status;
812   EDKII_MEMORY_PROFILE_PROTOCOL     *ProfileProtocol;
813   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;
814   UINT8                             TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];
815 
816   if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {
817 
818     FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;
819     Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);
820     if (!EFI_ERROR (Status)) {
821       EfiInitializeFwVolDevicepathNode (FilePath, FileName);
822       SetDevicePathEndNode (FilePath + 1);
823 
824       Status = ProfileProtocol->RegisterImage (
825                                   ProfileProtocol,
826                                   (EFI_DEVICE_PATH_PROTOCOL *) FilePath,
827                                   ImageBase,
828                                   ImageSize,
829                                   FileType
830                                   );
831     }
832   }
833 }
834 
835 /**
836   This routine is entry point of ScriptSave driver.
837 
838   @param  ImageHandle           Handle for this drivers loaded image protocol.
839   @param  SystemTable           EFI system table.
840 
841   @retval EFI_OUT_OF_RESOURCES  No enough resource
842   @retval EFI_SUCCESS           Succesfully installed the ScriptSave driver.
843   @retval other                 Errors occured.
844 
845 **/
846 EFI_STATUS
847 EFIAPI
InitializeScriptSaveOnS3SaveState(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)848 InitializeScriptSaveOnS3SaveState (
849   IN EFI_HANDLE           ImageHandle,
850   IN EFI_SYSTEM_TABLE     *SystemTable
851   )
852 {
853   UINT8                                         *Buffer;
854   UINTN                                         BufferSize;
855   PE_COFF_LOADER_IMAGE_CONTEXT                  ImageContext;
856   BOOT_SCRIPT_THUNK_DATA                        *BootScriptThunkData;
857   EFI_STATUS                                    Status;
858   VOID                                          *DevicePath;
859   EFI_PHYSICAL_ADDRESS                          MemoryAddress;
860   UINTN                                         PageNumber;
861   EFI_HANDLE                                    NewImageHandle;
862 
863   //
864   // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry
865   // point is loaded by DXE code which is the first time loaded. or else, it is already
866   // be reloaded be itself.This is a work-around
867   //
868   Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);
869   if (EFI_ERROR (Status)) {
870     //
871     // This is the first-time loaded by DXE core. reload itself to RESERVED mem
872     //
873     //
874     // A workaround: Here we install a dummy handle
875     //
876     NewImageHandle = NULL;
877     Status = gBS->InstallProtocolInterface (
878                     &NewImageHandle,
879                     &gEfiCallerIdGuid,
880                     EFI_NATIVE_INTERFACE,
881                     NULL
882                     );
883     ASSERT_EFI_ERROR (Status);
884 
885     Status = GetSectionFromAnyFv  (
886                &gEfiCallerIdGuid,
887                EFI_SECTION_PE32,
888                0,
889                (VOID **) &Buffer,
890                &BufferSize
891                );
892     ASSERT_EFI_ERROR (Status);
893     ImageContext.Handle    = Buffer;
894     ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
895     //
896     // Get information about the image being loaded
897     //
898     Status = PeCoffLoaderGetImageInfo (&ImageContext);
899     ASSERT_EFI_ERROR (Status);
900 
901     MemoryAddress = SIZE_4GB - 1;
902     if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {
903       PageNumber = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment));
904     } else {
905       PageNumber = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize);
906     }
907     Status  = gBS->AllocatePages (
908                      AllocateMaxAddress,
909                      EfiReservedMemoryType,
910                      PageNumber,
911                      &MemoryAddress
912                      );
913     ASSERT_EFI_ERROR (Status);
914     ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)MemoryAddress;
915     //
916     // Align buffer on section boundry
917     //
918     ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
919     ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
920     //
921     // Load the image to our new buffer
922     //
923     Status = PeCoffLoaderLoadImage (&ImageContext);
924     ASSERT_EFI_ERROR (Status);
925 
926     //
927     // Relocate the image in our new buffer
928     //
929     Status = PeCoffLoaderRelocateImage (&ImageContext);
930     ASSERT_EFI_ERROR (Status);
931 
932     //
933     // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer
934     //
935     gBS->FreePool (Buffer);
936 
937     //
938     // Flush the instruction cache so the image data is written before we execute it
939     //
940     InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
941 
942     RegisterMemoryProfileImage (
943       &gEfiCallerIdGuid,
944       ImageContext.ImageAddress,
945       ImageContext.ImageSize,
946       EFI_FV_FILETYPE_DRIVER
947     );
948 
949     Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
950     ASSERT_EFI_ERROR (Status);
951 
952     //
953     // Additional step for BootScriptThunk integrity
954     //
955 
956     //
957     // Allocate BootScriptThunkData
958     //
959     BootScriptThunkData = AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA));
960     ASSERT (BootScriptThunkData != NULL);
961 
962     BootScriptThunkData->BootScriptThunkBase   = ImageContext.ImageAddress;
963     BootScriptThunkData->BootScriptThunkLength = ImageContext.ImageSize;
964     //
965     // Set BootScriptThunkData
966     //
967     PcdSet64 (BootScriptThunkDataPtr, (UINT64)(UINTN)BootScriptThunkData);
968     return EFI_SUCCESS;
969   } else {
970     //
971     // the entry point is invoked after reloading. following code only run in RESERVED mem
972     //
973 
974     //
975     // Locate and cache PI S3 Save State Protocol.
976     //
977     Status = gBS->LocateProtocol (
978                     &gEfiS3SaveStateProtocolGuid,
979                     NULL,
980                     (VOID **) &mS3SaveState
981                     );
982     ASSERT_EFI_ERROR (Status);
983 
984     return gBS->InstallProtocolInterface (
985                   &mHandle,
986                   &gEfiBootScriptSaveProtocolGuid,
987                   EFI_NATIVE_INTERFACE,
988                   &mS3ScriptSave
989                   );
990   }
991 }
992 
993 
994