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