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