]>
Commit | Line | Data |
---|---|---|
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 | |
c4b90c07 | 5 | Copyright (c) 2010 - 2015, 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 | |
17 | EFI_HANDLE mHandle;\r | |
18 | EFI_BOOT_SCRIPT_SAVE_PROTOCOL mS3ScriptSave = {\r | |
19 | BootScriptWrite,\r | |
20 | BootScriptCloseTable\r | |
21 | };\r | |
22 | EFI_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 | |
35 | EFI_STATUS\r | |
36 | Execute32BitCode (\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 | |
51 | EFI_STATUS\r | |
52 | EFIAPI\r | |
53 | FrameworkBootScriptDispatchStub (\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 | |
87 | EFI_STATUS\r | |
88 | BootScriptIoWrite (\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 | |
121 | EFI_STATUS\r | |
122 | BootScriptIoReadWrite (\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 | |
156 | EFI_STATUS\r | |
157 | BootScriptMemWrite (\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 | |
191 | EFI_STATUS\r | |
192 | BootScriptMemReadWrite (\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 | |
226 | EFI_STATUS\r | |
227 | BootScriptPciCfgWrite (\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 | |
261 | EFI_STATUS\r | |
262 | BootScriptPciCfgReadWrite (\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 | |
295 | EFI_STATUS\r | |
296 | BootScriptPciCfg2Write (\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 | |
333 | EFI_STATUS\r | |
334 | BootScriptPciCfg2ReadWrite (\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 | |
370 | EFI_STATUS\r | |
371 | BootScriptSmbusExecute (\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 | |
410 | EFI_STATUS\r | |
411 | BootScriptStall (\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 | |
437 | EFI_STATUS\r | |
438 | BootScriptDispatch (\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 | |
465 | EFI_STATUS\r | |
466 | FrameworkBootScriptDispatch (\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 | |
498 | EFI_STATUS\r | |
499 | BootScriptMemPoll (\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 | |
555 | EFI_STATUS\r | |
556 | BootScriptDispatch2 (\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 | |
583 | EFI_STATUS\r | |
584 | BootScriptInformation (\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 | |
633 | EFI_STATUS\r | |
634 | EFIAPI\r | |
635 | BootScriptWrite (\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 | |
773 | EFI_STATUS\r | |
774 | EFIAPI\r | |
775 | BootScriptCloseTable (\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 | |
09fc7dbb SZ |
794 | /**\r |
795 | Register image to memory profile.\r | |
796 | \r | |
797 | @param FileName File name of the image.\r | |
798 | @param ImageBase Image base address.\r | |
799 | @param ImageSize Image size.\r | |
800 | @param FileType File type of the image.\r | |
801 | \r | |
802 | **/\r | |
803 | VOID\r | |
804 | RegisterMemoryProfileImage (\r | |
805 | IN EFI_GUID *FileName,\r | |
806 | IN PHYSICAL_ADDRESS ImageBase,\r | |
807 | IN UINT64 ImageSize,\r | |
808 | IN EFI_FV_FILETYPE FileType\r | |
809 | )\r | |
810 | {\r | |
811 | EFI_STATUS Status;\r | |
812 | EDKII_MEMORY_PROFILE_PROTOCOL *ProfileProtocol;\r | |
813 | MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FilePath;\r | |
814 | UINT8 TempBuffer[sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + sizeof (EFI_DEVICE_PATH_PROTOCOL)];\r | |
815 | \r | |
816 | if ((PcdGet8 (PcdMemoryProfilePropertyMask) & BIT0) != 0) {\r | |
817 | \r | |
818 | FilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempBuffer;\r | |
819 | Status = gBS->LocateProtocol (&gEdkiiMemoryProfileGuid, NULL, (VOID **) &ProfileProtocol);\r | |
820 | if (!EFI_ERROR (Status)) {\r | |
821 | EfiInitializeFwVolDevicepathNode (FilePath, FileName);\r | |
822 | SetDevicePathEndNode (FilePath + 1);\r | |
823 | \r | |
824 | Status = ProfileProtocol->RegisterImage (\r | |
825 | ProfileProtocol,\r | |
826 | (EFI_DEVICE_PATH_PROTOCOL *) FilePath,\r | |
827 | ImageBase,\r | |
828 | ImageSize,\r | |
829 | FileType\r | |
830 | );\r | |
831 | }\r | |
832 | }\r | |
833 | }\r | |
834 | \r | |
ba9978cf | 835 | /**\r |
836 | This routine is entry point of ScriptSave driver.\r | |
837 | \r | |
26a76fbc | 838 | @param ImageHandle Handle for this drivers loaded image protocol.\r |
ba9978cf | 839 | @param SystemTable EFI system table.\r |
840 | \r | |
841 | @retval EFI_OUT_OF_RESOURCES No enough resource\r | |
842 | @retval EFI_SUCCESS Succesfully installed the ScriptSave driver.\r | |
843 | @retval other Errors occured.\r | |
844 | \r | |
845 | **/\r | |
846 | EFI_STATUS\r | |
847 | EFIAPI\r | |
848 | InitializeScriptSaveOnS3SaveState (\r | |
849 | IN EFI_HANDLE ImageHandle,\r | |
850 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
851 | )\r | |
852 | {\r | |
d766b228 JY |
853 | UINT8 *Buffer;\r |
854 | UINTN BufferSize;\r | |
d766b228 JY |
855 | PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r |
856 | BOOT_SCRIPT_THUNK_DATA *BootScriptThunkData;\r | |
857 | EFI_STATUS Status;\r | |
858 | VOID *DevicePath;\r | |
a1fe1d6d LG |
859 | EFI_PHYSICAL_ADDRESS MemoryAddress;\r |
860 | UINTN PageNumber;\r | |
ca1677d8 | 861 | EFI_HANDLE NewImageHandle;\r |
d766b228 | 862 | \r |
ba9978cf | 863 | //\r |
d766b228 JY |
864 | // Test if the gEfiCallerIdGuid of this image is already installed. if not, the entry\r |
865 | // point is loaded by DXE code which is the first time loaded. or else, it is already\r | |
866 | // be reloaded be itself.This is a work-around\r | |
ba9978cf | 867 | //\r |
d766b228 JY |
868 | Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, &DevicePath);\r |
869 | if (EFI_ERROR (Status)) {\r | |
870 | //\r | |
bad73446 | 871 | // This is the first-time loaded by DXE core. reload itself to RESERVED mem\r |
d766b228 JY |
872 | //\r |
873 | //\r | |
e0d216f6 | 874 | // A workaround: Here we install a dummy handle\r |
d766b228 | 875 | //\r |
ca1677d8 | 876 | NewImageHandle = NULL;\r |
d766b228 | 877 | Status = gBS->InstallProtocolInterface (\r |
ca1677d8 | 878 | &NewImageHandle,\r |
d766b228 JY |
879 | &gEfiCallerIdGuid,\r |
880 | EFI_NATIVE_INTERFACE,\r | |
ca1677d8 | 881 | NULL\r |
d766b228 | 882 | );\r |
e0d216f6 | 883 | ASSERT_EFI_ERROR (Status);\r |
d766b228 JY |
884 | \r |
885 | Status = GetSectionFromAnyFv (\r | |
886 | &gEfiCallerIdGuid,\r | |
887 | EFI_SECTION_PE32,\r | |
888 | 0,\r | |
889 | (VOID **) &Buffer,\r | |
890 | &BufferSize\r | |
891 | );\r | |
e0d216f6 | 892 | ASSERT_EFI_ERROR (Status);\r |
d766b228 JY |
893 | ImageContext.Handle = Buffer;\r |
894 | ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r | |
895 | //\r | |
896 | // Get information about the image being loaded\r | |
897 | //\r | |
898 | Status = PeCoffLoaderGetImageInfo (&ImageContext);\r | |
e0d216f6 | 899 | ASSERT_EFI_ERROR (Status);\r |
a1fe1d6d LG |
900 | \r |
901 | MemoryAddress = SIZE_4GB - 1;\r | |
c4b90c07 | 902 | if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r |
0ac71f15 | 903 | PageNumber = EFI_SIZE_TO_PAGES ((UINTN) (ImageContext.ImageSize + ImageContext.SectionAlignment));\r |
c4b90c07 | 904 | } else {\r |
0ac71f15 | 905 | PageNumber = EFI_SIZE_TO_PAGES ((UINTN) ImageContext.ImageSize);\r |
c4b90c07 | 906 | }\r |
a1fe1d6d LG |
907 | Status = gBS->AllocatePages (\r |
908 | AllocateMaxAddress,\r | |
bad73446 | 909 | EfiReservedMemoryType,\r |
a1fe1d6d LG |
910 | PageNumber,\r |
911 | &MemoryAddress\r | |
912 | );\r | |
e0d216f6 | 913 | ASSERT_EFI_ERROR (Status);\r |
a1fe1d6d | 914 | ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)MemoryAddress;\r |
d766b228 JY |
915 | //\r |
916 | // Align buffer on section boundry\r | |
917 | //\r | |
918 | ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r | |
919 | ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r | |
920 | //\r | |
921 | // Load the image to our new buffer\r | |
922 | //\r | |
923 | Status = PeCoffLoaderLoadImage (&ImageContext);\r | |
e0d216f6 | 924 | ASSERT_EFI_ERROR (Status);\r |
ba9978cf | 925 | \r |
d766b228 JY |
926 | //\r |
927 | // Relocate the image in our new buffer\r | |
928 | //\r | |
929 | Status = PeCoffLoaderRelocateImage (&ImageContext);\r | |
e0d216f6 SZ |
930 | ASSERT_EFI_ERROR (Status);\r |
931 | \r | |
932 | //\r | |
933 | // Free the buffer allocated by ReadSection since the image has been relocated in the new buffer\r | |
934 | //\r | |
935 | gBS->FreePool (Buffer);\r | |
d766b228 | 936 | \r |
d766b228 JY |
937 | //\r |
938 | // Flush the instruction cache so the image data is written before we execute it\r | |
939 | //\r | |
940 | InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r | |
09fc7dbb SZ |
941 | \r |
942 | RegisterMemoryProfileImage (\r | |
943 | &gEfiCallerIdGuid,\r | |
944 | ImageContext.ImageAddress,\r | |
945 | ImageContext.ImageSize,\r | |
946 | EFI_FV_FILETYPE_DRIVER\r | |
947 | );\r | |
948 | \r | |
ca1677d8 | 949 | Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);\r |
e0d216f6 SZ |
950 | ASSERT_EFI_ERROR (Status);\r |
951 | \r | |
d766b228 JY |
952 | //\r |
953 | // Additional step for BootScriptThunk integrity\r | |
954 | //\r | |
955 | \r | |
956 | //\r | |
957 | // Allocate BootScriptThunkData\r | |
958 | //\r | |
959 | BootScriptThunkData = AllocatePool (sizeof (BOOT_SCRIPT_THUNK_DATA));\r | |
e0d216f6 | 960 | ASSERT (BootScriptThunkData != NULL);\r |
d766b228 JY |
961 | \r |
962 | BootScriptThunkData->BootScriptThunkBase = ImageContext.ImageAddress;\r | |
963 | BootScriptThunkData->BootScriptThunkLength = ImageContext.ImageSize;\r | |
964 | //\r | |
965 | // Set BootScriptThunkData\r | |
966 | //\r | |
967 | PcdSet64 (BootScriptThunkDataPtr, (UINT64)(UINTN)BootScriptThunkData); \r | |
968 | return EFI_SUCCESS;\r | |
969 | } else {\r | |
970 | //\r | |
bad73446 | 971 | // the entry point is invoked after reloading. following code only run in RESERVED mem\r |
d766b228 JY |
972 | //\r |
973 | \r | |
974 | //\r | |
975 | // Locate and cache PI S3 Save State Protocol.\r | |
976 | //\r | |
977 | Status = gBS->LocateProtocol (\r | |
978 | &gEfiS3SaveStateProtocolGuid, \r | |
979 | NULL, \r | |
980 | (VOID **) &mS3SaveState\r | |
981 | );\r | |
982 | ASSERT_EFI_ERROR (Status);\r | |
983 | \r | |
984 | return gBS->InstallProtocolInterface (\r | |
ba9978cf | 985 | &mHandle,\r |
986 | &gEfiBootScriptSaveProtocolGuid,\r | |
987 | EFI_NATIVE_INTERFACE,\r | |
988 | &mS3ScriptSave\r | |
989 | );\r | |
d766b228 | 990 | }\r |
ba9978cf | 991 | }\r |
992 | \r | |
993 | \r |