• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Implementation for S3 SMM Boot Script Saver state driver.
3 
4   Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions
8   of the BSD License which accompanies this distribution.  The
9   full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 #include "InternalSmmSaveState.h"
17 
18 EFI_S3_SMM_SAVE_STATE_PROTOCOL    mS3SmmSaveState = {
19    BootScriptWrite,
20    BootScriptInsert,
21    BootScriptLabel,
22    BootScriptCompare
23   };
24 /**
25   Internal function to add IO write opcode to the table.
26 
27   @param  Marker                The variable argument list to get the opcode
28                                 and associated attributes.
29 
30   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
31   @retval EFI_SUCCESS           Opcode is added.
32 
33 **/
34 EFI_STATUS
BootScriptWriteIoWrite(IN VA_LIST Marker)35 BootScriptWriteIoWrite (
36   IN VA_LIST                       Marker
37   )
38 {
39   S3_BOOT_SCRIPT_LIB_WIDTH Width;
40   UINT64                Address;
41   UINTN                 Count;
42   UINT8                 *Buffer;
43 
44   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
45   Address     = VA_ARG (Marker, UINT64);
46   Count       = VA_ARG (Marker, UINTN);
47   Buffer      = VA_ARG (Marker, UINT8 *);
48 
49   return S3BootScriptSaveIoWrite (Width, Address, Count, Buffer);
50 }
51 /**
52   Internal function to add IO read/write opcode to the table.
53 
54   @param  Marker                The variable argument list to get the opcode
55                                 and associated attributes.
56 
57   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
58   @retval EFI_SUCCESS           Opcode is added.
59 
60 **/
61 EFI_STATUS
BootScriptWriteIoReadWrite(IN VA_LIST Marker)62 BootScriptWriteIoReadWrite (
63   IN VA_LIST                       Marker
64   )
65 {
66   S3_BOOT_SCRIPT_LIB_WIDTH Width;
67   UINT64                Address;
68   UINT8                 *Data;
69   UINT8                 *DataMask;
70 
71   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
72   Address     = VA_ARG (Marker, UINT64);
73   Data        = VA_ARG (Marker, UINT8 *);
74   DataMask    = VA_ARG (Marker, UINT8 *);
75 
76   return S3BootScriptSaveIoReadWrite (Width, Address, Data, DataMask);
77 }
78 
79 /**
80   Internal function to add memory write opcode to the table.
81 
82   @param  Marker                The variable argument list to get the opcode
83                                 and associated attributes.
84 
85   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
86   @retval EFI_SUCCESS           Opcode is added.
87 
88 **/
89 EFI_STATUS
BootScriptWriteMemWrite(IN VA_LIST Marker)90 BootScriptWriteMemWrite (
91   IN VA_LIST                       Marker
92   )
93 {
94   S3_BOOT_SCRIPT_LIB_WIDTH Width;
95   UINT64                Address;
96   UINTN                 Count;
97   UINT8                 *Buffer;
98 
99   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
100   Address     = VA_ARG (Marker, UINT64);
101   Count       = VA_ARG (Marker, UINTN);
102   Buffer      = VA_ARG (Marker, UINT8 *);
103 
104   return S3BootScriptSaveMemWrite (Width, Address, Count, Buffer);
105 }
106 
107 /**
108   Internal function to add memory read/write opcode to the table.
109 
110   @param  Marker                The variable argument list to get the opcode
111                                 and associated attributes.
112 
113   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
114   @retval EFI_SUCCESS           Opcode is added.
115 
116 **/
117 EFI_STATUS
BootScriptWriteMemReadWrite(IN VA_LIST Marker)118 BootScriptWriteMemReadWrite (
119   IN VA_LIST                       Marker
120   )
121 {
122   S3_BOOT_SCRIPT_LIB_WIDTH Width;
123   UINT64                Address;
124   UINT8                 *Data;
125   UINT8                 *DataMask;
126 
127   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
128   Address     = VA_ARG (Marker, UINT64);
129   Data        = VA_ARG (Marker, UINT8 *);
130   DataMask    = VA_ARG (Marker, UINT8 *);
131 
132   return S3BootScriptSaveMemReadWrite (Width, Address, Data, DataMask);
133 }
134 
135 /**
136   Internal function to add PciCfg write opcode to the table.
137 
138   @param  Marker                The variable argument list to get the opcode
139                                 and associated attributes.
140 
141   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
142   @retval EFI_SUCCESS           Opcode is added.
143 
144 **/
145 EFI_STATUS
BootScriptWritePciCfgWrite(IN VA_LIST Marker)146 BootScriptWritePciCfgWrite (
147   IN VA_LIST                       Marker
148   )
149 {
150   S3_BOOT_SCRIPT_LIB_WIDTH Width;
151   UINT64                Address;
152   UINTN                 Count;
153   UINT8                 *Buffer;
154 
155   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
156   Address     = VA_ARG (Marker, UINT64);
157   Count       = VA_ARG (Marker, UINTN);
158   Buffer      = VA_ARG (Marker, UINT8 *);
159 
160   return S3BootScriptSavePciCfgWrite (Width, Address, Count, Buffer);
161 }
162 
163 /**
164   Internal function to PciCfg read/write opcode to the table.
165 
166   @param  Marker                The variable argument list to get the opcode
167                                 and associated attributes.
168 
169   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
170   @retval EFI_SUCCESS           Opcode is added.
171 
172 **/
173 EFI_STATUS
BootScriptWritePciCfgReadWrite(IN VA_LIST Marker)174 BootScriptWritePciCfgReadWrite (
175   IN VA_LIST                       Marker
176   )
177 {
178   S3_BOOT_SCRIPT_LIB_WIDTH Width;
179   UINT64                Address;
180   UINT8                 *Data;
181   UINT8                 *DataMask;
182 
183   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
184   Address     = VA_ARG (Marker, UINT64);
185   Data        = VA_ARG (Marker, UINT8 *);
186   DataMask    = VA_ARG (Marker, UINT8 *);
187 
188   return S3BootScriptSavePciCfgReadWrite (Width, Address, Data, DataMask);
189 }
190 /**
191   Internal function to add PciCfg2 write opcode to the table.
192 
193   @param  Marker                The variable argument list to get the opcode
194                                 and associated attributes.
195 
196   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
197   @retval EFI_SUCCESS           Opcode is added.
198 
199 **/
200 EFI_STATUS
BootScriptWritePciCfg2Write(IN VA_LIST Marker)201 BootScriptWritePciCfg2Write (
202   IN VA_LIST                       Marker
203   )
204 {
205   S3_BOOT_SCRIPT_LIB_WIDTH Width;
206   UINT64                Address;
207   UINTN                 Count;
208   UINT8                 *Buffer;
209   UINT16                Segment;
210 
211   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
212   Address     = VA_ARG (Marker, UINT64);
213   Count       = VA_ARG (Marker, UINTN);
214   Buffer      = VA_ARG (Marker, UINT8 *);
215   Segment     = VA_ARG (Marker, UINT16);
216 
217   return S3BootScriptSavePciCfg2Write (Width, Segment, Address, Count, Buffer);
218 }
219 
220 /**
221   Internal function to PciCfg2 read/write opcode to the table.
222 
223   @param  Marker                The variable argument list to get the opcode
224                                 and associated attributes.
225 
226   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
227   @retval EFI_SUCCESS           Opcode is added.
228 
229 **/
230 EFI_STATUS
BootScriptWritePciCfg2ReadWrite(IN VA_LIST Marker)231 BootScriptWritePciCfg2ReadWrite (
232   IN VA_LIST                       Marker
233   )
234 {
235   S3_BOOT_SCRIPT_LIB_WIDTH Width;
236   UINT16                Segment;
237   UINT64                Address;
238   UINT8                 *Data;
239   UINT8                 *DataMask;
240 
241   Width       = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
242   Address     = VA_ARG (Marker, UINT64);
243   Segment     = VA_ARG (Marker, UINT16);
244   Data        = VA_ARG (Marker, UINT8 *);
245   DataMask    = VA_ARG (Marker, UINT8 *);
246 
247   return S3BootScriptSavePciCfg2ReadWrite (Width, Segment, Address, Data, DataMask);
248 }
249 /**
250   Internal function to add smbus execute opcode to the table.
251 
252   @param  Marker                The variable argument list to get the opcode
253                                 and associated attributes.
254 
255   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
256   @retval EFI_SUCCESS           Opcode is added.
257 
258 **/
259 EFI_STATUS
BootScriptWriteSmbusExecute(IN VA_LIST Marker)260 BootScriptWriteSmbusExecute (
261   IN VA_LIST                       Marker
262   )
263 {
264   EFI_SMBUS_DEVICE_ADDRESS  SlaveAddress;
265   EFI_SMBUS_DEVICE_COMMAND  Command;
266   EFI_SMBUS_OPERATION       Operation;
267   BOOLEAN                   PecCheck;
268   VOID                     *Buffer;
269   UINTN                    *DataSize;
270   UINTN                     SmBusAddress;
271 
272   SlaveAddress.SmbusDeviceAddress = VA_ARG (Marker, UINTN);
273   Command                         = VA_ARG (Marker, EFI_SMBUS_DEVICE_COMMAND);
274   Operation                       = VA_ARG (Marker, EFI_SMBUS_OPERATION);
275   PecCheck                        = VA_ARG (Marker, BOOLEAN);
276   SmBusAddress                    = SMBUS_LIB_ADDRESS (SlaveAddress.SmbusDeviceAddress,Command,0,PecCheck);
277   DataSize                        = VA_ARG (Marker, UINTN *);
278   Buffer                          = VA_ARG (Marker, VOID *);
279 
280   return S3BootScriptSaveSmbusExecute (SmBusAddress, Operation, DataSize, Buffer);
281 }
282 /**
283   Internal function to add stall opcode to the table.
284 
285   @param  Marker                The variable argument list to get the opcode
286                                 and associated attributes.
287 
288   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
289   @retval EFI_SUCCESS           Opcode is added.
290 
291 **/
292 EFI_STATUS
BootScriptWriteStall(IN VA_LIST Marker)293 BootScriptWriteStall (
294   IN VA_LIST                       Marker
295   )
296 {
297   UINT32                Duration;
298 
299   Duration    = VA_ARG (Marker, UINT32);
300 
301   return S3BootScriptSaveStall (Duration);
302 }
303 
304 /**
305   Internal function to add Save jmp address according to DISPATCH_OPCODE.
306   We ignore "Context" parameter
307 
308   @param  Marker                The variable argument list to get the opcode
309                                 and associated attributes.
310 
311   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
312   @retval EFI_SUCCESS           Opcode is added.
313 
314 **/
315 EFI_STATUS
BootScriptWriteDispatch(IN VA_LIST Marker)316 BootScriptWriteDispatch (
317   IN VA_LIST                       Marker
318   )
319 {
320   VOID        *EntryPoint;
321 
322   EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
323   return S3BootScriptSaveDispatch (EntryPoint);
324 }
325 
326 /**
327   Internal function to add memory pool operation to the table.
328 
329   @param  Marker                The variable argument list to get the opcode
330                                 and associated attributes.
331 
332   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
333   @retval EFI_SUCCESS           Opcode is added.
334 
335 **/
336 EFI_STATUS
BootScriptWriteMemPoll(IN VA_LIST Marker)337 BootScriptWriteMemPoll (
338   IN VA_LIST                       Marker
339   )
340 {
341   S3_BOOT_SCRIPT_LIB_WIDTH   Width;
342   UINT64                     Address;
343   VOID                      *Data;
344   VOID                      *DataMask;
345   UINT64                     Delay;
346   UINT64                     LoopTimes;
347   UINT32                     Remainder;
348 
349   Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
350   Address  = VA_ARG (Marker, UINT64);
351   Data     = VA_ARG (Marker, VOID *);
352   DataMask = VA_ARG (Marker, VOID *);
353   Delay    = VA_ARG (Marker, UINT64);
354   //
355   // According to the spec, the interval between 2 polls is 100ns,
356   // but the unit of Duration for S3BootScriptSaveMemPoll() is microsecond(1000ns).
357   // Duration * 1000ns * LoopTimes = Delay * 100ns
358   // Duration will be minimum 1(microsecond) to be minimum deviation,
359   // so LoopTimes = Delay / 10.
360   //
361   LoopTimes = DivU64x32Remainder (
362                 Delay,
363                 10,
364                 &Remainder
365                 );
366   if (Remainder != 0) {
367     //
368     // If Remainder is not zero, LoopTimes will be rounded up by 1.
369     //
370     LoopTimes +=1;
371   }
372   return S3BootScriptSaveMemPoll (Width, Address, DataMask, Data, 1, LoopTimes);
373 
374 }
375 
376 /**
377   Internal function to add Save jmp address according to DISPATCH_OPCODE2.
378   The "Context" parameter is not ignored.
379 
380   @param  Marker                The variable argument list to get the opcode
381                                 and associated attributes.
382 
383   @retval EFI_OUT_OF_RESOURCES  Not enough resource to do operation.
384   @retval EFI_SUCCESS           Opcode is added.
385 
386 **/
387 EFI_STATUS
BootScriptWriteDispatch2(IN VA_LIST Marker)388 BootScriptWriteDispatch2 (
389   IN VA_LIST                       Marker
390   )
391 {
392   VOID                  *EntryPoint;
393   VOID                  *Context;
394 
395   EntryPoint = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
396   Context    = (VOID*)(UINTN)VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
397 
398   return S3BootScriptSaveDispatch2 (EntryPoint, Context);
399 }
400 /**
401   Internal function to add INFORAMTION opcode node to the table
402   list.
403   @param  Marker                The variable argument list to get the opcode
404                                 and associated attributes.
405 
406   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
407   @retval EFI_SUCCESS           The opcode entry is added to the  table
408                                 successfully.
409 **/
410 EFI_STATUS
BootScriptWriteInformation(IN VA_LIST Marker)411 BootScriptWriteInformation (
412   IN VA_LIST                       Marker
413   )
414 {
415   UINT32                InformationLength;
416   EFI_PHYSICAL_ADDRESS  Information;
417 
418   InformationLength = VA_ARG (Marker, UINT32);
419   Information = VA_ARG (Marker, EFI_PHYSICAL_ADDRESS);
420   return S3BootScriptSaveInformation (InformationLength, (VOID*)(UINTN)Information);
421 }
422 /**
423   Internal function to add IO poll opcode node  to the table
424   @param  Marker                The variable argument list to get the opcode
425                                 and associated attributes.
426 
427   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
428   @retval EFI_SUCCESS           The opcode entry is added to the  table
429                                 successfully.
430 **/
431 EFI_STATUS
BootScriptWriteIoPoll(IN VA_LIST Marker)432 BootScriptWriteIoPoll (
433   IN VA_LIST                       Marker
434   )
435 {
436    S3_BOOT_SCRIPT_LIB_WIDTH     Width;
437    UINT64                     Address;
438    VOID                      *Data;
439    VOID                      *DataMask;
440    UINT64                     Delay;
441 
442    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
443    Address  = VA_ARG (Marker, UINT64);
444    Data     = VA_ARG (Marker, VOID *);
445    DataMask = VA_ARG (Marker, VOID *);
446    Delay    = (UINT64)VA_ARG (Marker, UINT64);
447 
448    return S3BootScriptSaveIoPoll (Width, Address, Data, DataMask, Delay);
449 }
450 /**
451   Internal function to add PCI config poll opcode node to the table
452 
453   @param  Marker                The variable argument list to get the opcode
454                                 and associated attributes.
455 
456   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
457   @retval EFI_SUCCESS           The opcode entry is added to the  table
458                                 successfully.
459 **/
460 EFI_STATUS
BootScriptWritePciConfigPoll(IN VA_LIST Marker)461 BootScriptWritePciConfigPoll (
462   IN VA_LIST                       Marker
463   )
464 {
465    S3_BOOT_SCRIPT_LIB_WIDTH   Width;
466    UINT64                     Address;
467    VOID                      *Data;
468    VOID                      *DataMask;
469    UINT64                     Delay;
470 
471 
472    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
473    Address  = VA_ARG (Marker, UINT64);
474    Data     = VA_ARG (Marker, VOID *);
475    DataMask = VA_ARG (Marker, VOID *);
476    Delay    = (UINT64)VA_ARG (Marker, UINT64);
477 
478    return S3BootScriptSavePciPoll (Width, Address, Data, DataMask, Delay);
479 }
480 /**
481   Internal function to add PCI config 2 poll opcode node to the table
482 
483   @param  Marker                The variable argument list to get the opcode
484                                 and associated attributes.
485 
486   @retval EFI_OUT_OF_RESOURCES  Not enought resource to complete the operations.
487   @retval EFI_SUCCESS           The opcode entry is added to the  table
488                                 successfully.
489 **/
490 EFI_STATUS
BootScriptWritePciConfig2Poll(IN VA_LIST Marker)491 BootScriptWritePciConfig2Poll (
492   IN VA_LIST                       Marker
493   )
494 {
495    S3_BOOT_SCRIPT_LIB_WIDTH      Width;
496    UINT16                        Segment;
497    UINT64                        Address;
498    VOID                         *Data;
499    VOID                         *DataMask;
500    UINT64                        Delay;
501 
502    Width    = VA_ARG (Marker, S3_BOOT_SCRIPT_LIB_WIDTH);
503    Segment  = VA_ARG (Marker, UINT16);
504    Address  = VA_ARG (Marker, UINT64);
505    Data     = VA_ARG (Marker, VOID *);
506    DataMask = VA_ARG (Marker, VOID *);
507    Delay    = (UINT64)VA_ARG (Marker, UINT64);
508 
509    return S3BootScriptSavePci2Poll (Width, Segment, Address, Data, DataMask, Delay);
510 }
511 
512 /**
513   Adds a record into S3 boot script table.
514 
515   This function is used to store a boot script record into a given boot
516   script table. If the table specified by TableName is nonexistent in the
517   system, a new table will automatically be created and then the script record
518   will be added into the new table. This function is responsible for allocating
519   necessary memory for the script.
520 
521   This function has a variable parameter list. The exact parameter list depends on
522   the OpCode that is passed into the function. If an unsupported OpCode or illegal
523   parameter list is passed in, this function returns EFI_INVALID_PARAMETER.
524   If there are not enough resources available for storing more scripts, this function returns
525   EFI_OUT_OF_RESOURCES.
526 
527   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
528   @param  OpCode                The operation code (opcode) number.
529   @param  ...                   Argument list that is specific to each opcode.
530 
531   @retval EFI_SUCCESS           The operation succeeded. A record was added into the
532                                 specified script table.
533   @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
534                                 If the opcode is unknow or not supported because of the PCD
535                                 Feature Flags.
536   @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
537 
538 **/
539 EFI_STATUS
540 EFIAPI
BootScriptWrite(IN CONST EFI_S3_SAVE_STATE_PROTOCOL * This,IN UINT16 OpCode,...)541 BootScriptWrite (
542   IN CONST EFI_S3_SAVE_STATE_PROTOCOL         *This,
543   IN UINT16                                    OpCode,
544   ...
545   )
546 {
547   EFI_STATUS                Status;
548   VA_LIST                   Marker;
549   //
550   // Build script according to opcode
551   //
552   switch (OpCode) {
553 
554   case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
555     VA_START (Marker, OpCode);
556     Status = BootScriptWriteIoWrite (Marker);
557     VA_END (Marker);
558     break;
559 
560   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
561     VA_START (Marker, OpCode);
562     Status = BootScriptWriteIoReadWrite (Marker);
563     VA_END (Marker);
564     break;
565 
566   case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
567     VA_START (Marker, OpCode);
568     Status = BootScriptWriteMemWrite (Marker);
569     VA_END (Marker);
570     break;
571 
572   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
573     VA_START (Marker, OpCode);
574     Status = BootScriptWriteMemReadWrite (Marker);
575     VA_END (Marker);
576     break;
577 
578   case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
579     VA_START (Marker, OpCode);
580     Status = BootScriptWritePciCfgWrite (Marker);
581     VA_END (Marker);
582     break;
583 
584   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
585     VA_START (Marker, OpCode);
586     Status = BootScriptWritePciCfgReadWrite (Marker);
587     VA_END (Marker);
588     break;
589 
590   case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
591     VA_START (Marker, OpCode);
592     Status = BootScriptWriteSmbusExecute (Marker);
593     VA_END (Marker);
594     break;
595 
596   case EFI_BOOT_SCRIPT_STALL_OPCODE:
597     VA_START (Marker, OpCode);
598     Status = BootScriptWriteStall (Marker);
599     VA_END (Marker);
600 
601     break;
602 
603   case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
604     VA_START (Marker, OpCode);
605     Status = BootScriptWriteDispatch (Marker);
606     VA_END (Marker);
607     break;
608 
609   case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
610     VA_START (Marker, OpCode);
611     Status = BootScriptWriteDispatch2 (Marker);
612     VA_END (Marker);
613     break;
614 
615   case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
616     VA_START (Marker, OpCode);
617     Status = BootScriptWriteInformation (Marker);
618     VA_END (Marker);
619     break;
620 
621   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
622     VA_START (Marker, OpCode);
623     Status = BootScriptWriteMemPoll (Marker);
624     VA_END (Marker);
625     break;
626 
627   case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
628     VA_START (Marker, OpCode);
629     Status = BootScriptWritePciCfg2Write (Marker);
630     VA_END (Marker);
631     break;
632 
633   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
634     VA_START (Marker, OpCode);
635     Status = BootScriptWritePciCfg2ReadWrite (Marker);
636     VA_END (Marker);
637     break;
638 
639   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
640     VA_START (Marker, OpCode);
641     Status = BootScriptWriteIoPoll (Marker);
642     VA_END (Marker);
643     break;
644 
645   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
646     VA_START (Marker, OpCode);
647     Status = BootScriptWritePciConfigPoll (Marker);
648     VA_END (Marker);
649     break;
650 
651   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
652     VA_START (Marker, OpCode);
653     Status = BootScriptWritePciConfig2Poll (Marker);
654     VA_END (Marker);
655     break;
656 
657   default:
658     Status = EFI_INVALID_PARAMETER;
659     break;
660   }
661 
662   return Status;
663 }
664 /**
665   Insert a record into a specified Framework boot script table.
666 
667   This function is used to store an OpCode to be replayed as part of the S3 resume boot path. It is
668   assumed this protocol has platform specific mechanism to store the OpCode set and replay them
669   during the S3 resume.
670   The opcode is inserted before or after the specified position in the boot script table. If Position is
671   NULL then that position is after the last opcode in the table (BeforeOrAfter is FALSE) or before
672   the first opcode in the table (BeforeOrAfter is TRUE). The position which is pointed to by
673   Position upon return can be used for subsequent insertions.
674 
675   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
676   @param  BeforeOrAfter         Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
677                                 in the boot script table specified by Position. If Position is NULL or points to
678                                 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
679                                 of the table (if FALSE).
680   @param  Position              On entry, specifies the position in the boot script table where the opcode will be
681                                 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
682                                 the position of the inserted opcode in the boot script table.
683   @param  OpCode                The operation code (opcode) number.
684   @param  ...                   Argument list that is specific to each opcode.
685 
686   @retval EFI_SUCCESS           The operation succeeded. A record was added into the
687                                 specified script table.
688   @retval EFI_INVALID_PARAMETER The Opcode is an invalid opcode value or the Position is not a valid position in the boot script table..
689   @retval EFI_OUT_OF_RESOURCES  There is insufficient memory to store the boot script.
690 
691 **/
692 EFI_STATUS
693 EFIAPI
BootScriptInsert(IN CONST EFI_S3_SAVE_STATE_PROTOCOL * This,IN BOOLEAN BeforeOrAfter,IN OUT EFI_S3_BOOT_SCRIPT_POSITION * Position OPTIONAL,IN UINT16 OpCode,...)694 BootScriptInsert (
695   IN CONST EFI_S3_SAVE_STATE_PROTOCOL    *This,
696   IN       BOOLEAN                          BeforeOrAfter,
697   IN OUT   EFI_S3_BOOT_SCRIPT_POSITION     *Position OPTIONAL,
698   IN       UINT16                           OpCode,
699   ...
700   )
701 {
702   EFI_STATUS                Status;
703   VA_LIST                   Marker;
704   //
705   // Build script according to opcode
706   //
707   switch (OpCode) {
708 
709   case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
710     VA_START (Marker, OpCode);
711     Status = BootScriptWriteIoWrite (Marker);
712     VA_END (Marker);
713     break;
714 
715   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
716     VA_START (Marker, OpCode);
717     Status = BootScriptWriteIoReadWrite (Marker);
718     VA_END (Marker);
719     break;
720 
721   case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
722     VA_START (Marker, OpCode);
723     Status = BootScriptWriteMemWrite (Marker);
724     VA_END (Marker);
725     break;
726 
727   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
728     VA_START (Marker, OpCode);
729     Status = BootScriptWriteMemReadWrite (Marker);
730     VA_END (Marker);
731     break;
732 
733   case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
734     VA_START (Marker, OpCode);
735     Status = BootScriptWritePciCfgWrite (Marker);
736     VA_END (Marker);
737     break;
738 
739   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
740     VA_START (Marker, OpCode);
741     Status = BootScriptWritePciCfgReadWrite (Marker);
742     VA_END (Marker);
743     break;
744 
745   case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
746     VA_START (Marker, OpCode);
747     Status = BootScriptWriteSmbusExecute (Marker);
748     VA_END (Marker);
749     break;
750 
751   case EFI_BOOT_SCRIPT_STALL_OPCODE:
752     VA_START (Marker, OpCode);
753     Status = BootScriptWriteStall (Marker);
754     VA_END (Marker);
755 
756     break;
757 
758   case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
759     VA_START (Marker, OpCode);
760     Status = BootScriptWriteDispatch (Marker);
761     VA_END (Marker);
762     break;
763 
764   case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
765     VA_START (Marker, OpCode);
766     Status = BootScriptWriteDispatch2 (Marker);
767     VA_END (Marker);
768     break;
769 
770   case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
771     VA_START (Marker, OpCode);
772     Status = BootScriptWriteInformation (Marker);
773     VA_END (Marker);
774     break;
775 
776   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
777     VA_START (Marker, OpCode);
778     Status = BootScriptWriteMemPoll (Marker);
779     VA_END (Marker);
780     break;
781 
782   case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
783     VA_START (Marker, OpCode);
784     Status = BootScriptWritePciCfg2Write (Marker);
785     VA_END (Marker);
786     break;
787 
788   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
789     VA_START (Marker, OpCode);
790     Status = BootScriptWritePciCfg2ReadWrite (Marker);
791     VA_END (Marker);
792     break;
793 
794   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
795     VA_START (Marker, OpCode);
796     Status = BootScriptWriteIoPoll (Marker);
797     VA_END (Marker);
798     break;
799 
800   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
801     VA_START (Marker, OpCode);
802     Status = BootScriptWritePciConfigPoll (Marker);
803     VA_END (Marker);
804     break;
805 
806   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
807     VA_START (Marker, OpCode);
808     Status = BootScriptWritePciConfig2Poll (Marker);
809     VA_END (Marker);
810     break;
811 
812   default:
813     Status = EFI_INVALID_PARAMETER;
814     break;
815   }
816 
817   if (!EFI_ERROR (Status)) {
818    Status = S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
819   }
820   return Status;
821 }
822 /**
823   Find a label within the boot script table and, if not present, optionally create it.
824 
825   If the label Label is already exists in the boot script table, then no new label is created, the
826   position of the Label is returned in *Position and EFI_SUCCESS is returned.
827   If the label Label does not already exist and CreateIfNotFound is TRUE, then it will be
828   created before or after the specified position and EFI_SUCCESS is returned.
829   If the label Label does not already exist and CreateIfNotFound is FALSE, then
830   EFI_NOT_FOUND is returned.
831 
832   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
833   @param  BeforeOrAfter         Specifies whether the label is stored before (TRUE) or after (FALSE) the position in
834                                 the boot script table specified by Position. If Position is NULL or points to
835                                 NULL then the new label is inserted at the beginning of the table (if TRUE) or end of
836                                 the table (if FALSE).
837   @param  CreateIfNotFound      Specifies whether the label will be created if the label does not exists (TRUE) or not
838                                 (FALSE).
839   @param  Position              On entry, specifies the position in the boot script table where the label will be inserted,
840                                 either before or after, depending on BeforeOrAfter. On exit, specifies the position
841                                 of the inserted label in the boot script table.
842   @param  Label                 Points to the label which will be inserted in the boot script table.
843 
844   @retval EFI_SUCCESS           The label already exists or was inserted.
845   @retval EFI_INVALID_PARAMETER The Label is NULL or points to an empty string.
846   @retval EFI_INVALID_PARAMETER The Position is not a valid position in the boot script table.
847 
848 **/
849 EFI_STATUS
850 EFIAPI
BootScriptLabel(IN CONST EFI_S3_SAVE_STATE_PROTOCOL * This,IN BOOLEAN BeforeOrAfter,IN BOOLEAN CreateIfNotFound,IN OUT EFI_S3_BOOT_SCRIPT_POSITION * Position OPTIONAL,IN CONST CHAR8 * Label)851 BootScriptLabel (
852   IN CONST EFI_S3_SAVE_STATE_PROTOCOL           *This,
853   IN       BOOLEAN                               BeforeOrAfter,
854   IN       BOOLEAN                               CreateIfNotFound,
855   IN OUT   EFI_S3_BOOT_SCRIPT_POSITION          *Position OPTIONAL,
856   IN CONST CHAR8                                *Label
857   )
858 {
859 	return S3BootScriptLabel (BeforeOrAfter, CreateIfNotFound, Position, Label);
860 }
861 /**
862   Compare two positions in the boot script table and return their relative position.
863 
864   This function compares two positions in the boot script table and returns their relative positions. If
865   Position1 is before Position2, then -1 is returned. If Position1 is equal to Position2,
866   then 0 is returned. If Position1 is after Position2, then 1 is returned.
867 
868   @param  This                  A pointer to the EFI_S3_SAVE_STATE_PROTOCOL instance.
869   @param  Position1             The positions in the boot script table to compare
870   @param  Position2             The positions in the boot script table to compare
871   @param  RelativePosition      On return, points to the result of the comparison
872 
873   @retval EFI_SUCCESS           The operation succeeded.
874   @retval EFI_INVALID_PARAMETER The Position1 or Position2 is not a valid position in the boot script table.
875   @retval EFI_INVALID_PARAMETER The RelativePosition is NULL.
876 
877 **/
878 EFI_STATUS
879 EFIAPI
BootScriptCompare(IN CONST EFI_S3_SAVE_STATE_PROTOCOL * This,IN EFI_S3_BOOT_SCRIPT_POSITION Position1,IN EFI_S3_BOOT_SCRIPT_POSITION Position2,OUT UINTN * RelativePosition)880 BootScriptCompare (
881   IN CONST EFI_S3_SAVE_STATE_PROTOCOL      *This,
882   IN       EFI_S3_BOOT_SCRIPT_POSITION      Position1,
883   IN       EFI_S3_BOOT_SCRIPT_POSITION      Position2,
884   OUT      UINTN                           *RelativePosition
885   )
886 {
887 	return S3BootScriptCompare (Position1, Position2, RelativePosition);
888 }
889 /**
890   This routine is entry point of ScriptSave driver.
891 
892   @param  ImageHandle           Handle for this drivers loaded image protocol.
893   @param  SystemTable           EFI system table.
894 
895   @retval EFI_OUT_OF_RESOURCES  No enough resource
896   @retval EFI_SUCCESS           Succesfully installed the ScriptSave driver.
897   @retval other                 Errors occured.
898 
899 **/
900 EFI_STATUS
901 EFIAPI
InitializeSmmS3SaveState(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)902 InitializeSmmS3SaveState (
903   IN EFI_HANDLE           ImageHandle,
904   IN EFI_SYSTEM_TABLE     *SystemTable
905   )
906 {
907   EFI_HANDLE   Handle;
908 
909   if (!PcdGetBool (PcdAcpiS3Enable)) {
910     return EFI_UNSUPPORTED;
911   }
912 
913   Handle  = NULL;
914   return  gSmst->SmmInstallProtocolInterface (
915                    &Handle,
916                    &gEfiS3SmmSaveStateProtocolGuid,
917                    EFI_NATIVE_INTERFACE,
918                    &mS3SmmSaveState
919                    );
920 }
921