]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
MdeModulePkg PiDxeS3BootScriptLib: Remove the trailing white spaces
[mirror_edk2.git] / MdeModulePkg / Library / PiDxeS3BootScriptLib / BootScriptSave.c
CommitLineData
64d14edf 1/** @file\r
cfd79783
SZ
2 Save the S3 data to S3 boot script.\r
3\r
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
64d14edf 5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions\r
8 of the BSD License which accompanies this distribution. The\r
9 full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16#include "InternalBootScriptLib.h"\r
17\r
18/**\r
19\r
20 Data structure usage:\r
21\r
960f2d53
SZ
22 +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr\r
23 | SCRIPT_TABLE_PRIVATE_DATA | (mS3BootScriptTablePtr, Before SmmReadyToLock)\r
24 | TableBase |--- PcdS3BootScriptTablePrivateSmmDataPtr\r
25 | TableLength |--|-- (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)\r
26 | TableMemoryPageNumber |--|-|----\r
27 | AtRuntime | | | |\r
28 | InSmm | | | |\r
29 | BootTimeScriptLength |--|-|---|---\r
30 | SmmLocked | | | | |\r
31 | BackFromS3 | | | | |\r
32 +------------------------------+ | | | |\r
33 | | | |\r
34 +------------------------------+<-- | | |\r
35 | EFI_BOOT_SCRIPT_TABLE_HEADER | | | |\r
36 | TableLength |----|-- | |\r
37 +------------------------------+ | | | |\r
38 | ...... | | | | |\r
39 +------------------------------+<---- | | |\r
40 | EFI_BOOT_SCRIPT_TERMINATE | | | |\r
41 +------------------------------+<------ | |\r
42 | |\r
43 | |\r
44 mBootScriptDataBootTimeGuid LockBox: | |\r
45 Used to restore data after back from S3| |\r
46 to handle potential INSERT boot script | |\r
47 at runtime. | |\r
48 +------------------------------+ | |\r
49 | Boot Time Boot Script | | |\r
50 | Before SmmReadyToLock | | |\r
51 | | | |\r
52 | | | |\r
53 +------------------------------+ | |\r
54 | Boot Time Boot Script | | |\r
55 | After SmmReadyToLock InSmm | | |\r
56 | | | |\r
57 +------------------------------+<-------|--|\r
58 | |\r
59 | |\r
60 mBootScriptDataGuid LockBox: (IN_PLACE) | |\r
61 Used to restore data at S3 resume. | |\r
62 +------------------------------+ | |\r
63 | Boot Time Boot Script | | |\r
64 | Before SmmReadyToLock | | |\r
65 | | | |\r
66 | | | |\r
67 +------------------------------+ | |\r
68 | Boot Time Boot Script | | |\r
69 | After SmmReadyToLock InSmm | | |\r
70 | | | |\r
71 +------------------------------+<-------|---\r
72 | Runtime Boot Script | |\r
73 | After SmmReadyToLock InSmm | |\r
74 +------------------------------+ |\r
75 | ...... | |\r
76 +------------------------------+<--------\r
77\r
78\r
79 mBootScriptTableBaseGuid LockBox: (IN_PLACE)\r
80 +------------------------------+\r
81 | mS3BootScriptTablePtr-> |\r
82 | TableBase |\r
83 +------------------------------+\r
84\r
85\r
86 mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)\r
87 SMM private data with BackFromS3 = TRUE\r
88 at runtime. S3 will help restore it to\r
89 tell the Library the system is back from S3.\r
90 +------------------------------+\r
64d14edf 91 | SCRIPT_TABLE_PRIVATE_DATA |\r
960f2d53
SZ
92 | TableBase |\r
93 | TableLength |\r
94 | TableMemoryPageNumber |\r
95 | AtRuntime |\r
96 | InSmm |\r
97 | BootTimeScriptLength |\r
98 | SmmLocked |\r
99 | BackFromS3 = TRUE |\r
100 +------------------------------+\r
64d14edf 101\r
102**/\r
103\r
104SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTablePtr;\r
960f2d53 105\r
64d14edf 106//\r
960f2d53 107// Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.\r
64d14edf 108//\r
3aa764ed 109SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTableSmmPtr;\r
64d14edf 110\r
111EFI_GUID mBootScriptDataGuid = {\r
ce68d3bc 112 0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }\r
64d14edf 113};\r
114\r
960f2d53 115EFI_GUID mBootScriptDataBootTimeGuid = {\r
02f49fc2
SZ
116 0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }\r
117};\r
118\r
960f2d53 119EFI_GUID mBootScriptTableBaseGuid = {\r
ce68d3bc 120 0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }\r
64d14edf 121};\r
122\r
960f2d53
SZ
123EFI_GUID mBootScriptSmmPrivateDataGuid = {\r
124 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }\r
125};\r
126\r
cfd79783
SZ
127EFI_EVENT mEventDxeSmmReadyToLock = NULL;\r
128VOID *mRegistrationSmmExitBootServices = NULL;\r
129VOID *mRegistrationSmmLegacyBoot = NULL;\r
130VOID *mRegistrationSmmReadyToLock = NULL;\r
131BOOLEAN mS3BootScriptTableAllocated = FALSE;\r
132BOOLEAN mS3BootScriptTableSmmAllocated = FALSE;\r
a7636346 133EFI_SMM_SYSTEM_TABLE2 *mBootScriptSmst = NULL;\r
cfd79783 134\r
64d14edf 135/**\r
3a03e95e
SZ
136 This is an internal function to add a terminate node the entry, recalculate the table\r
137 length and fill into the table.\r
138\r
139 @return the base address of the boot script table.\r
64d14edf 140 **/\r
141UINT8*\r
142S3BootScriptInternalCloseTable (\r
143 VOID\r
144 )\r
145{\r
146 UINT8 *S3TableBase;\r
147 EFI_BOOT_SCRIPT_TERMINATE ScriptTerminate;\r
148 EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;\r
149 S3TableBase = mS3BootScriptTablePtr->TableBase;\r
3a03e95e 150\r
64d14edf 151 if (S3TableBase == NULL) {\r
152 //\r
153 // the table is not exist\r
154 //\r
155 return S3TableBase;\r
156 }\r
157 //\r
158 // Append the termination entry.\r
159 //\r
160 ScriptTerminate.OpCode = S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE;\r
161 ScriptTerminate.Length = (UINT8) sizeof (EFI_BOOT_SCRIPT_TERMINATE);\r
162 CopyMem (mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength, &ScriptTerminate, sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
163 //\r
164 // fill the table length\r
165 //\r
166 ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(mS3BootScriptTablePtr->TableBase);\r
167 ScriptTableInfo->TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);\r
3a03e95e
SZ
168\r
169\r
170\r
64d14edf 171 return S3TableBase;\r
172 //\r
3a03e95e 173 // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to\r
960f2d53
SZ
174 // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).\r
175 // Because maybe after SmmReadyToLock, we still need add entries into the table,\r
176 // and the entry should be added start before this TERMINATE node.\r
64d14edf 177 //\r
3a03e95e 178}\r
64d14edf 179\r
180/**\r
181 This function save boot script data to LockBox.\r
960f2d53 182\r
64d14edf 183**/\r
184VOID\r
185SaveBootScriptDataToLockBox (\r
186 VOID\r
187 )\r
188{\r
f6ec0c77 189 EFI_STATUS Status;\r
f6ec0c77 190\r
64d14edf 191 //\r
960f2d53
SZ
192 // Save whole memory copy into LockBox.\r
193 // It will be used to restore data at S3 resume.\r
64d14edf 194 //\r
195 Status = SaveLockBox (\r
196 &mBootScriptDataGuid,\r
197 (VOID *)mS3BootScriptTablePtr->TableBase,\r
960f2d53 198 EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)\r
64d14edf 199 );\r
200 ASSERT_EFI_ERROR (Status);\r
201\r
202 Status = SetLockBoxAttributes (&mBootScriptDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
203 ASSERT_EFI_ERROR (Status);\r
204\r
205 //\r
206 // Just need save TableBase.\r
207 // Do not update other field because they will NOT be used in S3.\r
208 //\r
209 Status = SaveLockBox (\r
960f2d53 210 &mBootScriptTableBaseGuid,\r
64d14edf 211 (VOID *)&mS3BootScriptTablePtr->TableBase,\r
212 sizeof(mS3BootScriptTablePtr->TableBase)\r
213 );\r
214 ASSERT_EFI_ERROR (Status);\r
215\r
960f2d53 216 Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
64d14edf 217 ASSERT_EFI_ERROR (Status);\r
218}\r
219\r
220/**\r
221 This is the Event call back function to notify the Library the system is entering\r
960f2d53 222 SmmLocked phase.\r
3a03e95e 223\r
64d14edf 224 @param Event Pointer to this event\r
3a03e95e 225 @param Context Event handler private data\r
64d14edf 226 **/\r
227VOID\r
228EFIAPI\r
229S3BootScriptEventCallBack (\r
230 IN EFI_EVENT Event,\r
231 IN VOID *Context\r
232 )\r
233{\r
234 EFI_STATUS Status;\r
235 VOID *Interface;\r
236\r
237 //\r
238 // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.\r
239 // Just return if it is not found.\r
240 //\r
241 Status = gBS->LocateProtocol (\r
242 &gEfiDxeSmmReadyToLockProtocolGuid,\r
243 NULL,\r
244 &Interface\r
245 );\r
246 if (EFI_ERROR (Status)) {\r
247 return ;\r
248 }\r
249\r
250 //\r
960f2d53
SZ
251 // Here we should tell the library that we are entering SmmLocked phase.\r
252 // and the memory page number occupied by the table should not grow anymore.\r
64d14edf 253 //\r
960f2d53 254 if (!mS3BootScriptTablePtr->SmmLocked) {\r
64d14edf 255 //\r
960f2d53
SZ
256 // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table\r
257 // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate\r
258 // node on every add to boot script table.\r
64d14edf 259 //\r
260 S3BootScriptInternalCloseTable ();\r
960f2d53 261 mS3BootScriptTablePtr->SmmLocked = TRUE;\r
64d14edf 262\r
263 //\r
264 // Save BootScript data to lockbox\r
265 //\r
266 SaveBootScriptDataToLockBox ();\r
267 }\r
960f2d53
SZ
268}\r
269\r
64d14edf 270/**\r
960f2d53
SZ
271 This is the Event call back function is triggered in SMM to notify the Library\r
272 the system is entering SmmLocked phase and set InSmm flag.\r
273\r
64d14edf 274 @param Protocol Points to the protocol's unique identifier\r
275 @param Interface Points to the interface instance\r
276 @param Handle The handle on which the interface was installed\r
277\r
278 @retval EFI_SUCCESS SmmEventCallback runs successfully\r
279 **/\r
280EFI_STATUS\r
281EFIAPI\r
282S3BootScriptSmmEventCallBack (\r
283 IN CONST EFI_GUID *Protocol,\r
284 IN VOID *Interface,\r
285 IN EFI_HANDLE Handle\r
286 )\r
287{\r
288 //\r
289 // Check if it is already done\r
290 //\r
3aa764ed 291 if (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr) {\r
64d14edf 292 return EFI_SUCCESS;\r
293 }\r
294\r
295 //\r
960f2d53 296 // Last chance to call-out, just make sure SmmLocked is set.\r
64d14edf 297 //\r
298 S3BootScriptEventCallBack (NULL, NULL);\r
299\r
300 //\r
3aa764ed 301 // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.\r
64d14edf 302 //\r
3aa764ed
SZ
303 if (mS3BootScriptTableSmmPtr->TableBase == NULL) {\r
304 CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof(*mS3BootScriptTablePtr));\r
960f2d53
SZ
305\r
306 //\r
307 // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.\r
308 // InSmm will only be checked if SmmLocked is TRUE.\r
309 //\r
310 mS3BootScriptTableSmmPtr->InSmm = TRUE;\r
3aa764ed 311 }\r
64d14edf 312 //\r
960f2d53 313 // We should not use ACPI Reserved copy, because it is not safe.\r
64d14edf 314 //\r
3aa764ed 315 mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;\r
64d14edf 316\r
960f2d53
SZ
317 return EFI_SUCCESS;\r
318}\r
319\r
320/**\r
321 This function is to save boot time boot script data to LockBox.\r
322\r
323 Because there may be INSERT boot script at runtime in SMM.\r
324 The boot time copy will be used to restore data after back from S3.\r
325 Otherwise the data inserted may cause some boot time boot script data lost\r
326 if only BootScriptData used.\r
327\r
328**/\r
329VOID\r
330SaveBootTimeDataToLockBox (\r
331 VOID\r
332 )\r
333{\r
334 EFI_STATUS Status;\r
335\r
64d14edf 336 //\r
960f2d53
SZ
337 // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,\r
338 // and then save the data to BootScriptDataBootTime LockBox.\r
64d14edf 339 //\r
960f2d53
SZ
340 Status = RestoreLockBox (\r
341 &mBootScriptDataGuid,\r
342 NULL,\r
343 NULL\r
344 );\r
345 ASSERT_EFI_ERROR (Status);\r
346\r
347 //\r
348 // Save BootScriptDataBootTime\r
349 // It will be used to restore data after back from S3.\r
350 //\r
351 Status = SaveLockBox (\r
352 &mBootScriptDataBootTimeGuid,\r
353 (VOID *) mS3BootScriptTablePtr->TableBase,\r
354 mS3BootScriptTablePtr->BootTimeScriptLength\r
355 );\r
356 ASSERT_EFI_ERROR (Status);\r
357}\r
358\r
359/**\r
360 This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.\r
361 S3 resume will help restore it to tell the Library the system is back from S3.\r
362\r
363**/\r
364VOID\r
365SaveSmmPriviateDataToLockBoxAtRuntime (\r
366 VOID\r
367 )\r
368{\r
369 EFI_STATUS Status;\r
370\r
371 //\r
372 // Save boot script SMM private data with BackFromS3 = TRUE.\r
373 //\r
374 mS3BootScriptTablePtr->BackFromS3 = TRUE;\r
375 Status = SaveLockBox (\r
376 &mBootScriptSmmPrivateDataGuid,\r
377 (VOID *) mS3BootScriptTablePtr,\r
378 sizeof (SCRIPT_TABLE_PRIVATE_DATA)\r
379 );\r
380 ASSERT_EFI_ERROR (Status);\r
381\r
382 Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);\r
383 ASSERT_EFI_ERROR (Status);\r
64d14edf 384\r
385 //\r
960f2d53 386 // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.\r
64d14edf 387 //\r
960f2d53
SZ
388 mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
389}\r
390\r
391/**\r
392 This is the Event call back function is triggered in SMM to notify the Library\r
393 the system is entering runtime phase.\r
394\r
395 @param[in] Protocol Points to the protocol's unique identifier\r
396 @param[in] Interface Points to the interface instance\r
397 @param[in] Handle The handle on which the interface was installed\r
398\r
399 @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully\r
400 **/\r
401EFI_STATUS\r
402EFIAPI\r
403S3BootScriptSmmAtRuntimeCallBack (\r
404 IN CONST EFI_GUID *Protocol,\r
405 IN VOID *Interface,\r
406 IN EFI_HANDLE Handle\r
407 )\r
408{\r
409 if (!mS3BootScriptTablePtr->AtRuntime) {\r
410 mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
411 SaveBootTimeDataToLockBox ();\r
412\r
413 mS3BootScriptTablePtr->AtRuntime = TRUE;\r
414 SaveSmmPriviateDataToLockBoxAtRuntime ();\r
415 }\r
64d14edf 416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420/**\r
421 Library Constructor.\r
3a03e95e
SZ
422 this function just identify it is a smm driver or non-smm driver linked against\r
423 with the library\r
64d14edf 424\r
425 @param ImageHandle The firmware allocated handle for the EFI image.\r
426 @param SystemTable A pointer to the EFI System Table.\r
427\r
cfd79783
SZ
428 @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.\r
429\r
64d14edf 430**/\r
431RETURN_STATUS\r
432EFIAPI\r
433S3BootScriptLibInitialize (\r
434 IN EFI_HANDLE ImageHandle,\r
435 IN EFI_SYSTEM_TABLE *SystemTable\r
436 )\r
437{\r
438 EFI_STATUS Status;\r
439 SCRIPT_TABLE_PRIVATE_DATA *S3TablePtr;\r
3aa764ed 440 SCRIPT_TABLE_PRIVATE_DATA *S3TableSmmPtr;\r
64d14edf 441 VOID *Registration;\r
442 EFI_SMM_BASE2_PROTOCOL *SmmBase2;\r
443 BOOLEAN InSmm;\r
64d14edf 444 EFI_PHYSICAL_ADDRESS Buffer;\r
445\r
446 S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateDataPtr);\r
447 //\r
448 // The Boot script private data is not be initialized. create it\r
449 //\r
450 if (S3TablePtr == 0) {\r
451 Buffer = SIZE_4GB - 1;\r
452 Status = gBS->AllocatePages (\r
453 AllocateMaxAddress,\r
960f2d53 454 EfiReservedMemoryType,\r
64d14edf 455 EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)),\r
456 &Buffer\r
457 );\r
cfd79783
SZ
458 ASSERT_EFI_ERROR (Status);\r
459 mS3BootScriptTableAllocated = TRUE;\r
64d14edf 460 S3TablePtr = (VOID *) (UINTN) Buffer;\r
461\r
ca49b6f9
SZ
462 Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64) (UINTN)S3TablePtr);\r
463 ASSERT_EFI_ERROR (Status);\r
cfd79783 464 ZeroMem (S3TablePtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
64d14edf 465 //\r
960f2d53 466 // Create event to notify the library system enter the SmmLocked phase.\r
64d14edf 467 //\r
cfd79783
SZ
468 mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent (\r
469 &gEfiDxeSmmReadyToLockProtocolGuid,\r
470 TPL_CALLBACK,\r
471 S3BootScriptEventCallBack,\r
472 NULL,\r
473 &Registration\r
474 );\r
475 ASSERT (mEventDxeSmmReadyToLock != NULL);\r
960f2d53 476 }\r
64d14edf 477 mS3BootScriptTablePtr = S3TablePtr;\r
478\r
479 //\r
480 // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.\r
481 //\r
482 Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID**) &SmmBase2);\r
483 if (EFI_ERROR (Status)) {\r
484 return RETURN_SUCCESS;\r
485 }\r
486 Status = SmmBase2->InSmm (SmmBase2, &InSmm);\r
487 if (EFI_ERROR (Status)) {\r
488 return RETURN_SUCCESS;\r
489 }\r
490 if (!InSmm) {\r
491 return RETURN_SUCCESS;\r
492 }\r
493 //\r
494 // Good, we are in SMM\r
495 //\r
a7636346 496 Status = SmmBase2->GetSmstLocation (SmmBase2, &mBootScriptSmst);\r
64d14edf 497 if (EFI_ERROR (Status)) {\r
498 return RETURN_SUCCESS;\r
499 }\r
500\r
3aa764ed
SZ
501 S3TableSmmPtr = (SCRIPT_TABLE_PRIVATE_DATA*)(UINTN)PcdGet64(PcdS3BootScriptTablePrivateSmmDataPtr);\r
502 //\r
503 // The Boot script private data in SMM is not be initialized. create it\r
504 //\r
505 if (S3TableSmmPtr == 0) {\r
a7636346
SZ
506 Status = mBootScriptSmst->SmmAllocatePool (\r
507 EfiRuntimeServicesData,\r
508 sizeof(SCRIPT_TABLE_PRIVATE_DATA),\r
509 (VOID **) &S3TableSmmPtr\r
510 );\r
cfd79783
SZ
511 ASSERT_EFI_ERROR (Status);\r
512 mS3BootScriptTableSmmAllocated = TRUE;\r
3aa764ed 513\r
ca49b6f9
SZ
514 Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64) (UINTN)S3TableSmmPtr);\r
515 ASSERT_EFI_ERROR (Status);\r
3aa764ed 516 ZeroMem (S3TableSmmPtr, sizeof(SCRIPT_TABLE_PRIVATE_DATA));\r
960f2d53
SZ
517\r
518 //\r
519 // Register SmmExitBootServices and SmmLegacyBoot notification.\r
520 //\r
a7636346
SZ
521 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
522 &gEdkiiSmmExitBootServicesProtocolGuid,\r
523 S3BootScriptSmmAtRuntimeCallBack,\r
524 &mRegistrationSmmExitBootServices\r
525 );\r
960f2d53
SZ
526 ASSERT_EFI_ERROR (Status);\r
527\r
a7636346
SZ
528 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
529 &gEdkiiSmmLegacyBootProtocolGuid,\r
530 S3BootScriptSmmAtRuntimeCallBack,\r
531 &mRegistrationSmmLegacyBoot\r
532 );\r
960f2d53 533 ASSERT_EFI_ERROR (Status);\r
3aa764ed
SZ
534 }\r
535 mS3BootScriptTableSmmPtr = S3TableSmmPtr;\r
536\r
64d14edf 537 //\r
960f2d53 538 // Register SmmReadyToLock notification.\r
64d14edf 539 //\r
a7636346
SZ
540 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
541 &gEfiSmmReadyToLockProtocolGuid,\r
542 S3BootScriptSmmEventCallBack,\r
543 &mRegistrationSmmReadyToLock\r
544 );\r
64d14edf 545 ASSERT_EFI_ERROR (Status);\r
546\r
547 return RETURN_SUCCESS;\r
548}\r
cfd79783
SZ
549\r
550/**\r
551 Library Destructor to free the resources allocated by\r
552 S3BootScriptLibInitialize() and unregister callbacks.\r
553\r
554 NOTICE: The destructor doesn't support unloading as a separate action, and it\r
555 only supports unloading if the containing driver's entry point function fails.\r
556\r
557 @param ImageHandle The firmware allocated handle for the EFI image.\r
558 @param SystemTable A pointer to the EFI System Table.\r
559\r
560 @retval RETURN_SUCCESS The destructor always returns RETURN_SUCCESS.\r
561\r
562**/\r
563RETURN_STATUS\r
564EFIAPI\r
565S3BootScriptLibDeinitialize (\r
566 IN EFI_HANDLE ImageHandle,\r
567 IN EFI_SYSTEM_TABLE *SystemTable\r
568 )\r
569{\r
570 EFI_STATUS Status;\r
571\r
572 DEBUG ((EFI_D_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName));\r
573\r
574 if (mEventDxeSmmReadyToLock != NULL) {\r
575 //\r
576 // Close the DxeSmmReadyToLock event.\r
577 //\r
578 Status = gBS->CloseEvent (mEventDxeSmmReadyToLock);\r
579 ASSERT_EFI_ERROR (Status);\r
580 }\r
581\r
a7636346 582 if (mBootScriptSmst != NULL) {\r
cfd79783
SZ
583 if (mRegistrationSmmExitBootServices != NULL) {\r
584 //\r
585 // Unregister SmmExitBootServices notification.\r
586 //\r
a7636346
SZ
587 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
588 &gEdkiiSmmExitBootServicesProtocolGuid,\r
589 NULL,\r
590 &mRegistrationSmmExitBootServices\r
591 );\r
cfd79783
SZ
592 ASSERT_EFI_ERROR (Status);\r
593 }\r
594 if (mRegistrationSmmLegacyBoot != NULL) {\r
595 //\r
596 // Unregister SmmLegacyBoot notification.\r
597 //\r
a7636346
SZ
598 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
599 &gEdkiiSmmLegacyBootProtocolGuid,\r
600 NULL,\r
601 &mRegistrationSmmLegacyBoot\r
602 );\r
cfd79783
SZ
603 ASSERT_EFI_ERROR (Status);\r
604 }\r
605 if (mRegistrationSmmReadyToLock != NULL) {\r
606 //\r
607 // Unregister SmmReadyToLock notification.\r
608 //\r
a7636346
SZ
609 Status = mBootScriptSmst->SmmRegisterProtocolNotify (\r
610 &gEfiSmmReadyToLockProtocolGuid,\r
611 NULL,\r
612 &mRegistrationSmmReadyToLock\r
613 );\r
cfd79783
SZ
614 ASSERT_EFI_ERROR (Status);\r
615 }\r
616 }\r
617\r
618 //\r
619 // Free the resources allocated and set PCDs to 0.\r
620 //\r
621 if (mS3BootScriptTableAllocated) {\r
622 Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES(sizeof(SCRIPT_TABLE_PRIVATE_DATA)));\r
623 ASSERT_EFI_ERROR (Status);\r
624 Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0);\r
625 ASSERT_EFI_ERROR (Status);\r
626 }\r
a7636346
SZ
627 if ((mBootScriptSmst != NULL) && mS3BootScriptTableSmmAllocated) {\r
628 Status = mBootScriptSmst->SmmFreePool (mS3BootScriptTableSmmPtr);\r
cfd79783
SZ
629 ASSERT_EFI_ERROR (Status);\r
630 Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0);\r
631 ASSERT_EFI_ERROR (Status);\r
632 }\r
633\r
634 return RETURN_SUCCESS;\r
635}\r
636\r
64d14edf 637/**\r
638 To get the start address from which a new boot time s3 boot script entry will write into.\r
639 If the table is not exist, the functio will first allocate a buffer for the table\r
3a03e95e 640 If the table buffer is not enough for the new entry, in non-smm mode, the funtion will\r
64d14edf 641 invoke reallocate to enlarge buffer.\r
3a03e95e 642\r
64d14edf 643 @param EntryLength the new entry length.\r
3a03e95e
SZ
644\r
645 @retval the address from which the a new s3 boot script entry will write into\r
64d14edf 646 **/\r
647UINT8*\r
648S3BootScriptGetBootTimeEntryAddAddress (\r
649 UINT8 EntryLength\r
650 )\r
651{\r
652 EFI_PHYSICAL_ADDRESS S3TableBase;\r
653 EFI_PHYSICAL_ADDRESS NewS3TableBase;\r
654 UINT8 *NewEntryPtr;\r
655 UINT32 TableLength;\r
656 UINT16 PageNumber;\r
657 EFI_STATUS Status;\r
658 EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;\r
3a03e95e 659\r
64d14edf 660 S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);\r
661 if (S3TableBase == 0) {\r
960f2d53 662 //\r
3a03e95e 663 // The table is not exist. This is the first to add entry.\r
960f2d53 664 // Allocate ACPI script table space under 4G memory.\r
64d14edf 665 //\r
666 S3TableBase = 0xffffffff;\r
667 Status = gBS->AllocatePages (\r
668 AllocateMaxAddress,\r
960f2d53 669 EfiReservedMemoryType,\r
64d14edf 670 2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
671 (EFI_PHYSICAL_ADDRESS*)&S3TableBase\r
672 );\r
3a03e95e 673\r
64d14edf 674 if (EFI_ERROR(Status)) {\r
675 ASSERT_EFI_ERROR (Status);\r
676 return 0;\r
677 }\r
678 //\r
679 // Fill Table Header\r
680 //\r
681 ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER*)(UINTN)S3TableBase;\r
682 ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;\r
683 ScriptTableInfo->Length = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
0a4a5b7b 684 ScriptTableInfo->Version = BOOT_SCRIPT_TABLE_VERSION;\r
64d14edf 685 ScriptTableInfo->TableLength = 0; // will be calculate at CloseTable\r
686 mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
687 mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)S3TableBase;\r
688 mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16)(2 + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));\r
689 }\r
3a03e95e 690\r
64d14edf 691 // Here we do not count the reserved memory for runtime script table.\r
960f2d53 692 PageNumber = (UINT16) (mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));\r
64d14edf 693 TableLength = mS3BootScriptTablePtr->TableLength;\r
960f2d53 694 if ((UINTN) EFI_PAGES_TO_SIZE ((UINTN) PageNumber) < (UINTN) (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {\r
3a03e95e 695 //\r
64d14edf 696 // The buffer is too small to hold the table, Reallocate the buffer\r
697 //\r
698 NewS3TableBase = 0xffffffff;\r
699 Status = gBS->AllocatePages (\r
700 AllocateMaxAddress,\r
960f2d53 701 EfiReservedMemoryType,\r
64d14edf 702 2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber),\r
703 (EFI_PHYSICAL_ADDRESS*)&NewS3TableBase\r
704 );\r
3a03e95e 705\r
64d14edf 706 if (EFI_ERROR(Status)) {\r
707 ASSERT_EFI_ERROR (Status);\r
708 return 0;\r
709 }\r
3a03e95e 710\r
64d14edf 711 CopyMem ((VOID*)(UINTN)NewS3TableBase, (VOID*)(UINTN)S3TableBase, TableLength);\r
712 gBS->FreePages (S3TableBase, mS3BootScriptTablePtr->TableMemoryPageNumber);\r
3a03e95e 713\r
64d14edf 714 mS3BootScriptTablePtr->TableBase = (UINT8*)(UINTN)NewS3TableBase;\r
3a03e95e 715 mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16) (2 + PageNumber + PcdGet16(PcdS3BootScriptRuntimeTableReservePageNumber));\r
64d14edf 716 }\r
717 //\r
3a03e95e 718 // calculate the the start address for the new entry.\r
64d14edf 719 //\r
720 NewEntryPtr = mS3BootScriptTablePtr->TableBase + TableLength;\r
3a03e95e 721\r
64d14edf 722 //\r
723 // update the table lenghth\r
724 //\r
725 mS3BootScriptTablePtr->TableLength = TableLength + EntryLength;\r
3a03e95e 726\r
64d14edf 727 //\r
728 // In the boot time, we will not append the termination entry to the boot script\r
3a03e95e
SZ
729 // table until the callers think there is no boot time data that should be added and\r
730 // it is caller's responsibility to explicit call the CloseTable.\r
64d14edf 731 //\r
732 //\r
3a03e95e
SZ
733\r
734 return NewEntryPtr;\r
64d14edf 735}\r
736/**\r
960f2d53 737 To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.\r
64d14edf 738 In this case, it should be ensured that there is enough buffer to hold the entry.\r
3a03e95e 739\r
64d14edf 740 @param EntryLength the new entry length.\r
3a03e95e 741\r
960f2d53 742 @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into\r
64d14edf 743 **/\r
744UINT8*\r
745S3BootScriptGetRuntimeEntryAddAddress (\r
746 UINT8 EntryLength\r
747 )\r
748{\r
749 UINT8 *NewEntryPtr;\r
3a03e95e
SZ
750\r
751 NewEntryPtr = NULL;\r
64d14edf 752 //\r
3a03e95e 753 // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.\r
64d14edf 754 //\r
960f2d53 755 if ((UINTN) (mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= (UINTN) EFI_PAGES_TO_SIZE ((UINTN) (mS3BootScriptTablePtr->TableMemoryPageNumber))) {\r
3a03e95e 756 NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;\r
64d14edf 757 mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;\r
758 //\r
759 // Append a terminate node on every insert\r
760 //\r
761 S3BootScriptInternalCloseTable ();\r
762 }\r
3a03e95e 763 return (UINT8*)NewEntryPtr;\r
64d14edf 764}\r
960f2d53
SZ
765\r
766/**\r
767 This function is to restore boot time boot script data from LockBox.\r
768\r
769**/\r
770VOID\r
771RestoreBootTimeDataFromLockBox (\r
772 VOID\r
773 )\r
774{\r
775 EFI_STATUS Status;\r
776 UINTN LockBoxLength;\r
777\r
778 //\r
779 // Restore boot time boot script data from LockBox.\r
780 //\r
781 LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;\r
782 Status = RestoreLockBox (\r
783 &mBootScriptDataBootTimeGuid,\r
784 (VOID *) mS3BootScriptTablePtr->TableBase,\r
785 &LockBoxLength\r
786 );\r
787 ASSERT_EFI_ERROR (Status);\r
788\r
789 //\r
790 // Update the data to BootScriptData LockBox.\r
791 //\r
792 Status = UpdateLockBox (\r
793 &mBootScriptDataGuid,\r
794 0,\r
795 (VOID *) mS3BootScriptTablePtr->TableBase,\r
796 LockBoxLength\r
797 );\r
798 ASSERT_EFI_ERROR (Status);\r
799\r
800 //\r
801 // Update TableLength.\r
802 //\r
803 mS3BootScriptTablePtr->TableLength = (UINT32) (mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
804}\r
805\r
64d14edf 806/**\r
807 To get the start address from which a new s3 boot script entry will write into.\r
3a03e95e 808\r
64d14edf 809 @param EntryLength the new entry length.\r
3a03e95e
SZ
810\r
811 @retval the address from which the a new s3 boot script entry will write into\r
812 **/\r
813UINT8*\r
64d14edf 814S3BootScriptGetEntryAddAddress (\r
815 UINT8 EntryLength\r
816 )\r
817{\r
818 UINT8* NewEntryPtr;\r
64d14edf 819\r
960f2d53 820 if (mS3BootScriptTablePtr->SmmLocked) {\r
64d14edf 821 //\r
960f2d53 822 // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.\r
64d14edf 823 //\r
824 if (!mS3BootScriptTablePtr->InSmm) {\r
825 //\r
960f2d53
SZ
826 // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.\r
827 // Do not use ASSERT, because we may have test to invoke this interface.\r
64d14edf 828 //\r
960f2d53 829 DEBUG ((EFI_D_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));\r
64d14edf 830 return NULL;\r
831 }\r
832\r
960f2d53 833 if (mS3BootScriptTablePtr->BackFromS3) {\r
64d14edf 834 //\r
960f2d53
SZ
835 // Back from S3, restore boot time boot script data from LockBox\r
836 // and set BackFromS3 flag back to FALSE.\r
64d14edf 837 //\r
960f2d53
SZ
838 RestoreBootTimeDataFromLockBox ();\r
839 mS3BootScriptTablePtr->BackFromS3 = FALSE;\r
64d14edf 840 }\r
841\r
842 NewEntryPtr = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);\r
960f2d53 843 } else {\r
64d14edf 844 NewEntryPtr = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);\r
3a03e95e 845 }\r
64d14edf 846 return NewEntryPtr;\r
3a03e95e
SZ
847\r
848}\r
64d14edf 849\r
850/**\r
851 Sync BootScript LockBox data.\r
02f49fc2
SZ
852\r
853 @param Script The address from where the boot script has been added or updated.\r
854\r
64d14edf 855**/\r
856VOID\r
857SyncBootScript (\r
02f49fc2 858 IN UINT8 *Script\r
64d14edf 859 )\r
860{\r
861 EFI_STATUS Status;\r
960f2d53
SZ
862 UINT32 ScriptOffset;\r
863 UINT32 TotalScriptLength;\r
02f49fc2 864\r
960f2d53 865 if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {\r
02f49fc2 866 //\r
960f2d53
SZ
867 // If it is not after SmmReadyToLock in SMM,\r
868 // just return.\r
02f49fc2 869 //\r
64d14edf 870 return ;\r
871 }\r
02f49fc2 872\r
960f2d53
SZ
873 ScriptOffset = (UINT32) (Script - mS3BootScriptTablePtr->TableBase);\r
874\r
875 TotalScriptLength = (UINT32) (mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));\r
876\r
64d14edf 877 //\r
02f49fc2 878 // Update BootScriptData\r
64d14edf 879 // So in S3 resume, the data can be restored correctly.\r
880 //\r
881 Status = UpdateLockBox (\r
882 &mBootScriptDataGuid,\r
02f49fc2
SZ
883 ScriptOffset,\r
884 (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),\r
960f2d53
SZ
885 TotalScriptLength - ScriptOffset\r
886 );\r
887 ASSERT_EFI_ERROR (Status);\r
888\r
889 //\r
890 // Now the length field is updated, need sync to lockbox.\r
891 // So at S3 resume, the data can be restored correctly.\r
892 //\r
893 Status = UpdateLockBox (\r
894 &mBootScriptDataGuid,\r
895 OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),\r
896 &TotalScriptLength,\r
897 sizeof (TotalScriptLength)\r
64d14edf 898 );\r
899 ASSERT_EFI_ERROR (Status);\r
900}\r
901\r
3a03e95e
SZ
902/**\r
903 This is an function to close the S3 boot script table. The function could only be called in\r
904 BOOT time phase. To comply with the Framework spec definition on\r
64d14edf 905 EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:\r
906 1. Closes the specified boot script table\r
3a03e95e
SZ
907 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.\r
908 Once this function is called, the table maintained by the library will be destroyed\r
64d14edf 909 after it is copied into the allocated pool.\r
3a03e95e 910 3. Any attempts to add a script record after calling this function will cause a new table\r
64d14edf 911 to be created by the library.\r
3a03e95e 912 4. The base address of the allocated pool will be returned in Address. Note that after\r
64d14edf 913 using the boot script table, the CALLER is responsible for freeing the pool that is allocated\r
3a03e95e 914 by this function.\r
64d14edf 915\r
3a03e95e 916 In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is\r
64d14edf 917 for Framework Spec compatibility.\r
3a03e95e
SZ
918\r
919 If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out\r
920 how to get the script to run at S3 resume because the boot script maintained by the lib will be\r
64d14edf 921 destroyed.\r
3a03e95e
SZ
922\r
923 @return the base address of the new copy of the boot script table.\r
64d14edf 924 @note this function could only called in boot time phase\r
925\r
926**/\r
927UINT8*\r
928EFIAPI\r
929S3BootScriptCloseTable (\r
930 VOID\r
931 )\r
932{\r
933 UINT8 *S3TableBase;\r
934 UINT32 TableLength;\r
935 UINT8 *Buffer;\r
936 EFI_STATUS Status;\r
937 EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;\r
3a03e95e
SZ
938\r
939 S3TableBase = mS3BootScriptTablePtr->TableBase;\r
64d14edf 940 if (S3TableBase == 0) {\r
3a03e95e 941 return 0;\r
64d14edf 942 }\r
943 //\r
944 // Append the termination record the S3 boot script table\r
945 //\r
946 S3BootScriptInternalCloseTable();\r
947 TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);\r
948 //\r
3a03e95e 949 // Allocate the buffer and copy the boot script to the buffer.\r
64d14edf 950 //\r
951 Status = gBS->AllocatePool (\r
952 EfiBootServicesData,\r
953 (UINTN)TableLength,\r
954 (VOID **) &Buffer\r
955 );\r
956 if (EFI_ERROR (Status)) {\r
3a03e95e 957 return 0;\r
64d14edf 958 }\r
959 CopyMem (Buffer, S3TableBase, TableLength);\r
3a03e95e 960\r
64d14edf 961 //\r
3a03e95e 962 // Destroy the table maintained by the library so that the next write operation\r
64d14edf 963 // will write the record to the first entry of the table.\r
964 //\r
965 // Fill the table header.\r
966 ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER*)S3TableBase;\r
967 ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;\r
968 ScriptTableInfo->Length = (UINT8) sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
969 ScriptTableInfo->TableLength = 0; // will be calculate at close the table\r
3a03e95e 970\r
64d14edf 971 mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);\r
972 return Buffer;\r
973}\r
974/**\r
3a03e95e 975 Save I/O write to boot script\r
64d14edf 976\r
977 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
978 @param Address The base address of the I/O operations.\r
979 @param Count The number of I/O operations to perform.\r
980 @param Buffer The source buffer from which to write data.\r
981\r
982 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
983 @retval RETURN_SUCCESS Opcode is added.\r
984**/\r
985RETURN_STATUS\r
986EFIAPI\r
987S3BootScriptSaveIoWrite (\r
988 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
989 IN UINT64 Address,\r
990 IN UINTN Count,\r
991 IN VOID *Buffer\r
992 )\r
993\r
994{\r
995 UINT8 Length;\r
996 UINT8 *Script;\r
997 UINT8 WidthInByte;\r
998 EFI_BOOT_SCRIPT_IO_WRITE ScriptIoWrite;\r
999\r
1000 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1001 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count));\r
3a03e95e 1002\r
64d14edf 1003 Script = S3BootScriptGetEntryAddAddress (Length);\r
1004 if (Script == NULL) {\r
1005 return RETURN_OUT_OF_RESOURCES;\r
1006 }\r
1007 //\r
1008 // save script data\r
1009 //\r
1010 ScriptIoWrite.OpCode = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;\r
1011 ScriptIoWrite.Length = Length;\r
1012 ScriptIoWrite.Width = Width;\r
1013 ScriptIoWrite.Address = Address;\r
1014 ScriptIoWrite.Count = (UINT32) Count;\r
1015 CopyMem ((VOID*)Script, (VOID*)&ScriptIoWrite, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));\r
1016 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);\r
1017\r
02f49fc2 1018 SyncBootScript (Script);\r
64d14edf 1019\r
1020 return RETURN_SUCCESS;\r
1021}\r
1022\r
1023/**\r
1024 Adds a record for an I/O modify operation into a S3 boot script table\r
1025\r
1026 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1027 @param Address The base address of the I/O operations.\r
1028 @param Data A pointer to the data to be OR-ed.\r
1029 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register\r
1030\r
1031 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1032 @retval RETURN_SUCCESS Opcode is added.\r
1033**/\r
1034RETURN_STATUS\r
1035EFIAPI\r
1036S3BootScriptSaveIoReadWrite (\r
1037 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1038 IN UINT64 Address,\r
1039 IN VOID *Data,\r
1040 IN VOID *DataMask\r
1041 )\r
1042{\r
1043 UINT8 Length;\r
1044 UINT8 *Script;\r
1045 UINT8 WidthInByte;\r
1046 EFI_BOOT_SCRIPT_IO_READ_WRITE ScriptIoReadWrite;\r
1047\r
1048 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1049 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + (WidthInByte * 2));\r
3a03e95e 1050\r
64d14edf 1051 Script = S3BootScriptGetEntryAddAddress (Length);\r
1052 if (Script == NULL) {\r
1053 return RETURN_OUT_OF_RESOURCES;\r
1054 }\r
1055 //\r
1056 // Build script data\r
1057 //\r
1058 ScriptIoReadWrite.OpCode = EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE;\r
1059 ScriptIoReadWrite.Length = Length;\r
1060 ScriptIoReadWrite.Width = Width;\r
1061 ScriptIoReadWrite.Address = Address;\r
3a03e95e 1062\r
64d14edf 1063 CopyMem ((VOID*)Script, (VOID*)&ScriptIoReadWrite, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));\r
1064 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);\r
1065 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);\r
1066\r
02f49fc2 1067 SyncBootScript (Script);\r
64d14edf 1068\r
1069 return RETURN_SUCCESS;\r
1070}\r
1071/**\r
1072 Adds a record for a memory write operation into a specified boot script table.\r
1073\r
1074 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1075 @param Address The base address of the memory operations\r
1076 @param Count The number of memory operations to perform.\r
1077 @param Buffer The source buffer from which to write the data.\r
1078\r
1079 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1080 @retval RETURN_SUCCESS Opcode is added.\r
1081**/\r
1082RETURN_STATUS\r
1083EFIAPI\r
1084S3BootScriptSaveMemWrite (\r
1085 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1086 IN UINT64 Address,\r
1087 IN UINTN Count,\r
1088 IN VOID *Buffer\r
1089 )\r
1090{\r
1091 UINT8 Length;\r
1092 UINT8 *Script;\r
1093 UINT8 WidthInByte;\r
1094 EFI_BOOT_SCRIPT_MEM_WRITE ScriptMemWrite;\r
3a03e95e 1095\r
64d14edf 1096 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1097 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE) + (WidthInByte * Count));\r
3a03e95e 1098\r
64d14edf 1099 Script = S3BootScriptGetEntryAddAddress (Length);\r
1100 if (Script == NULL) {\r
1101 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1102 }\r
64d14edf 1103 //\r
1104 // Build script data\r
1105 //\r
1106 ScriptMemWrite.OpCode = EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE;\r
1107 ScriptMemWrite.Length = Length;\r
1108 ScriptMemWrite.Width = Width;\r
1109 ScriptMemWrite.Address = Address;\r
1110 ScriptMemWrite.Count = (UINT32) Count;\r
3a03e95e 1111\r
64d14edf 1112 CopyMem ((VOID*)Script, (VOID*)&ScriptMemWrite, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));\r
1113 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);\r
3a03e95e 1114\r
02f49fc2 1115 SyncBootScript (Script);\r
64d14edf 1116\r
1117 return RETURN_SUCCESS;\r
1118}\r
1119/**\r
1120 Adds a record for a memory modify operation into a specified boot script table.\r
1121\r
1122 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1123 @param Address The base address of the memory operations. Address needs alignment if required\r
1124 @param Data A pointer to the data to be OR-ed.\r
1125 @param DataMask A pointer to the data mask to be AND-ed with the data read from the register.\r
1126\r
1127 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1128 @retval RETURN_SUCCESS Opcode is added.\r
1129**/\r
1130RETURN_STATUS\r
1131EFIAPI\r
1132S3BootScriptSaveMemReadWrite (\r
1133 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1134 IN UINT64 Address,\r
1135 IN VOID *Data,\r
1136 IN VOID *DataMask\r
1137 )\r
1138{\r
1139 UINT8 Length;\r
1140 UINT8 *Script;\r
1141 UINT8 WidthInByte;\r
1142 EFI_BOOT_SCRIPT_MEM_READ_WRITE ScriptMemReadWrite;\r
3a03e95e 1143\r
64d14edf 1144 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1145 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + (WidthInByte * 2));\r
3a03e95e 1146\r
64d14edf 1147 Script = S3BootScriptGetEntryAddAddress (Length);\r
1148 if (Script == NULL) {\r
1149 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1150 }\r
64d14edf 1151 //\r
1152 // Build script data\r
3a03e95e 1153 //\r
64d14edf 1154 ScriptMemReadWrite.OpCode = EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE;\r
1155 ScriptMemReadWrite.Length = Length;\r
1156 ScriptMemReadWrite.Width = Width;\r
1157 ScriptMemReadWrite.Address = Address;\r
3a03e95e 1158\r
64d14edf 1159 CopyMem ((VOID*)Script, (VOID*)&ScriptMemReadWrite , sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE));\r
1160 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);\r
1161 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);\r
1162\r
02f49fc2 1163 SyncBootScript (Script);\r
64d14edf 1164\r
1165 return RETURN_SUCCESS;\r
1166}\r
1167/**\r
1168 Adds a record for a PCI configuration space write operation into a specified boot script table.\r
1169\r
1170 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1171 @param Address The address within the PCI configuration space.\r
1172 @param Count The number of PCI operations to perform.\r
1173 @param Buffer The source buffer from which to write the data.\r
1174\r
1175 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1176 @retval RETURN_SUCCESS Opcode is added.\r
2a956f74
SZ
1177 @note A known Limitations in the implementation which is 64bits operations are not supported.\r
1178\r
64d14edf 1179**/\r
1180RETURN_STATUS\r
1181EFIAPI\r
1182S3BootScriptSavePciCfgWrite (\r
1183 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1184 IN UINT64 Address,\r
1185 IN UINTN Count,\r
1186 IN VOID *Buffer\r
1187 )\r
1188{\r
1189 UINT8 Length;\r
1190 UINT8 *Script;\r
1191 UINT8 WidthInByte;\r
1192 EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite;\r
1193\r
2a956f74
SZ
1194 if (Width == S3BootScriptWidthUint64 ||\r
1195 Width == S3BootScriptWidthFifoUint64 ||\r
1196 Width == S3BootScriptWidthFillUint64) {\r
1197 return EFI_INVALID_PARAMETER;\r
1198 }\r
1199\r
64d14edf 1200 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1201 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));\r
3a03e95e 1202\r
64d14edf 1203 Script = S3BootScriptGetEntryAddAddress (Length);\r
1204 if (Script == NULL) {\r
1205 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1206 }\r
64d14edf 1207 //\r
1208 // Build script data\r
1209 //\r
1210 ScriptPciWrite.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;\r
1211 ScriptPciWrite.Length = Length;\r
1212 ScriptPciWrite.Width = Width;\r
1213 ScriptPciWrite.Address = Address;\r
1214 ScriptPciWrite.Count = (UINT32) Count;\r
3a03e95e 1215\r
64d14edf 1216 CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));\r
1217 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);\r
3a03e95e 1218\r
02f49fc2 1219 SyncBootScript (Script);\r
64d14edf 1220\r
1221 return RETURN_SUCCESS;\r
1222}\r
1223/**\r
1224 Adds a record for a PCI configuration space modify operation into a specified boot script table.\r
1225\r
1226 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1227 @param Address The address within the PCI configuration space.\r
1228 @param Data A pointer to the data to be OR-ed.The size depends on Width.\r
1229 @param DataMask A pointer to the data mask to be AND-ed.\r
1230\r
1231 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1232 @retval RETURN__SUCCESS Opcode is added.\r
2a956f74
SZ
1233 @note A known Limitations in the implementation which is 64bits operations are not supported.\r
1234\r
64d14edf 1235**/\r
1236RETURN_STATUS\r
1237EFIAPI\r
1238S3BootScriptSavePciCfgReadWrite (\r
1239 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1240 IN UINT64 Address,\r
1241 IN VOID *Data,\r
1242 IN VOID *DataMask\r
1243 )\r
1244{\r
1245 UINT8 Length;\r
1246 UINT8 *Script;\r
1247 UINT8 WidthInByte;\r
1248 EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite;\r
1249\r
2a956f74
SZ
1250 if (Width == S3BootScriptWidthUint64 ||\r
1251 Width == S3BootScriptWidthFifoUint64 ||\r
1252 Width == S3BootScriptWidthFillUint64) {\r
1253 return EFI_INVALID_PARAMETER;\r
1254 }\r
1255\r
64d14edf 1256 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1257 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));\r
3a03e95e 1258\r
64d14edf 1259 Script = S3BootScriptGetEntryAddAddress (Length);\r
1260 if (Script == NULL) {\r
1261 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1262 }\r
64d14edf 1263 //\r
1264 // Build script data\r
3a03e95e 1265 //\r
64d14edf 1266 ScriptPciReadWrite.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE;\r
1267 ScriptPciReadWrite.Length = Length;\r
1268 ScriptPciReadWrite.Width = Width;\r
1269 ScriptPciReadWrite.Address = Address;\r
3a03e95e 1270\r
64d14edf 1271 CopyMem ((VOID*)Script, (VOID*)&ScriptPciReadWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));\r
1272 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE)), Data, WidthInByte);\r
1273 CopyMem (\r
1274 (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + WidthInByte),\r
1275 DataMask,\r
1276 WidthInByte\r
1277 );\r
1278\r
02f49fc2 1279 SyncBootScript (Script);\r
64d14edf 1280\r
1281 return RETURN_SUCCESS;\r
1282}\r
1283/**\r
02f49fc2 1284 Adds a record for a PCI configuration 2 space write operation into a specified boot script table.\r
64d14edf 1285\r
1286 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1287 @param Segment The PCI segment number for Address.\r
1288 @param Address The address within the PCI configuration space.\r
1289 @param Count The number of PCI operations to perform.\r
1290 @param Buffer The source buffer from which to write the data.\r
1291\r
1292 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1293 @retval RETURN_SUCCESS Opcode is added.\r
2a956f74
SZ
1294 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
1295\r
64d14edf 1296**/\r
1297RETURN_STATUS\r
1298EFIAPI\r
1299S3BootScriptSavePciCfg2Write (\r
1300 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1301 IN UINT16 Segment,\r
1302 IN UINT64 Address,\r
1303 IN UINTN Count,\r
1304 IN VOID *Buffer\r
1305 )\r
1306{\r
1307 UINT8 Length;\r
1308 UINT8 *Script;\r
1309 UINT8 WidthInByte;\r
1310 EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2;\r
2a956f74
SZ
1311\r
1312 if (Segment != 0 ||\r
1313 Width == S3BootScriptWidthUint64 ||\r
1314 Width == S3BootScriptWidthFifoUint64 ||\r
1315 Width == S3BootScriptWidthFillUint64) {\r
1316 return EFI_INVALID_PARAMETER;\r
1317 }\r
1318\r
64d14edf 1319 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1320 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));\r
3a03e95e 1321\r
64d14edf 1322 Script = S3BootScriptGetEntryAddAddress (Length);\r
1323 if (Script == NULL) {\r
1324 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1325 }\r
64d14edf 1326 //\r
1327 // Build script data\r
1328 //\r
1329 ScriptPciWrite2.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE;\r
1330 ScriptPciWrite2.Length = Length;\r
1331 ScriptPciWrite2.Width = Width;\r
1332 ScriptPciWrite2.Address = Address;\r
1333 ScriptPciWrite2.Segment = Segment;\r
1334 ScriptPciWrite2.Count = (UINT32)Count;\r
3a03e95e 1335\r
64d14edf 1336 CopyMem ((VOID*)Script, (VOID*)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));\r
1337 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);\r
1338\r
02f49fc2 1339 SyncBootScript (Script);\r
64d14edf 1340\r
1341 return RETURN_SUCCESS;\r
1342}\r
1343/**\r
02f49fc2 1344 Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.\r
64d14edf 1345\r
1346 @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.\r
1347 @param Segment The PCI segment number for Address.\r
1348 @param Address The address within the PCI configuration space.\r
1349 @param Data A pointer to the data to be OR-ed. The size depends on Width.\r
1350 @param DataMask A pointer to the data mask to be AND-ed.\r
1351\r
1352 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1353 @retval RETURN_SUCCESS Opcode is added.\r
2a956f74
SZ
1354 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
1355\r
64d14edf 1356**/\r
1357RETURN_STATUS\r
1358EFIAPI\r
1359S3BootScriptSavePciCfg2ReadWrite (\r
1360 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1361 IN UINT16 Segment,\r
1362 IN UINT64 Address,\r
1363 IN VOID *Data,\r
1364 IN VOID *DataMask\r
1365 )\r
1366{\r
1367 UINT8 Length;\r
1368 UINT8 *Script;\r
1369 UINT8 WidthInByte;\r
1370 EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2;\r
2a956f74
SZ
1371\r
1372 if (Segment != 0 ||\r
1373 Width == S3BootScriptWidthUint64 ||\r
1374 Width == S3BootScriptWidthFifoUint64 ||\r
1375 Width == S3BootScriptWidthFillUint64) {\r
1376 return EFI_INVALID_PARAMETER;\r
1377 }\r
3a03e95e 1378\r
64d14edf 1379 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1380 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));\r
3a03e95e 1381\r
64d14edf 1382 Script = S3BootScriptGetEntryAddAddress (Length);\r
1383 if (Script == NULL) {\r
1384 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1385 }\r
64d14edf 1386 //\r
1387 // Build script data\r
1388 //\r
1389 ScriptPciReadWrite2.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE;\r
1390 ScriptPciReadWrite2.Length = Length;\r
1391 ScriptPciReadWrite2.Width = Width;\r
1392 ScriptPciReadWrite2.Segment = Segment;\r
1393 ScriptPciReadWrite2.Address = Address;\r
3a03e95e 1394\r
64d14edf 1395 CopyMem ((VOID*)Script, (VOID*)&ScriptPciReadWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));\r
1396 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE)), Data, WidthInByte);\r
1397 CopyMem (\r
1398 (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + WidthInByte),\r
1399 DataMask,\r
1400 WidthInByte\r
1401 );\r
3a03e95e 1402\r
02f49fc2 1403 SyncBootScript (Script);\r
64d14edf 1404\r
1405 return RETURN_SUCCESS;\r
1406}\r
2a956f74
SZ
1407\r
1408/**\r
1409 Checks the parameter of S3BootScriptSaveSmbusExecute().\r
1410\r
1411 This function checks the input parameters of SmbusExecute(). If the input parameters are valid\r
1412 for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain\r
1413 error code based on the input SMBus bus protocol.\r
1414\r
3a03e95e 1415 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,\r
2a956f74
SZ
1416 and PEC.\r
1417 @param Operation Signifies which particular SMBus hardware protocol instance that\r
1418 it will use to execute the SMBus transactions. This SMBus\r
1419 hardware protocol is defined by the SMBus Specification and is\r
1420 not related to EFI.\r
1421 @param Length Signifies the number of bytes that this operation will do. The\r
1422 maximum number of bytes can be revision specific and operation\r
1423 specific. This field will contain the actual number of bytes that\r
1424 are executed for this operation. Not all operations require this\r
1425 argument.\r
1426 @param Buffer Contains the value of data to execute to the SMBus slave device.\r
1427 Not all operations require this argument. The length of this\r
1428 buffer is identified by Length.\r
1429\r
1430 @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus\r
3a03e95e 1431 protocol.\r
2a956f74
SZ
1432 @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.\r
1433 @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead\r
1434 and EfiSmbusQuickWrite. Length is outside the range of valid\r
1435 values.\r
1436 @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.\r
1437 @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.\r
1438\r
1439**/\r
1440EFI_STATUS\r
1441CheckParameters (\r
1442 IN UINTN SmBusAddress,\r
1443 IN EFI_SMBUS_OPERATION Operation,\r
1444 IN OUT UINTN *Length,\r
1445 IN VOID *Buffer\r
1446 )\r
1447{\r
1448 EFI_STATUS Status;\r
1449 UINTN RequiredLen;\r
1450 EFI_SMBUS_DEVICE_COMMAND Command;\r
1451 BOOLEAN PecCheck;\r
3a03e95e 1452\r
2a956f74
SZ
1453 Command = SMBUS_LIB_COMMAND (SmBusAddress);\r
1454 PecCheck = SMBUS_LIB_PEC (SmBusAddress);\r
1455 //\r
1456 // Set default value to be 2:\r
3a03e95e 1457 // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.\r
2a956f74
SZ
1458 //\r
1459 RequiredLen = 2;\r
1460 Status = EFI_SUCCESS;\r
1461 switch (Operation) {\r
1462 case EfiSmbusQuickRead:\r
1463 case EfiSmbusQuickWrite:\r
1464 if (PecCheck || Command != 0) {\r
1465 return EFI_UNSUPPORTED;\r
1466 }\r
1467 break;\r
1468 case EfiSmbusReceiveByte:\r
1469 case EfiSmbusSendByte:\r
1470 if (Command != 0) {\r
1471 return EFI_UNSUPPORTED;\r
1472 }\r
1473 //\r
1474 // Cascade to check length parameter.\r
1475 //\r
1476 case EfiSmbusReadByte:\r
1477 case EfiSmbusWriteByte:\r
1478 RequiredLen = 1;\r
1479 //\r
1480 // Cascade to check length parameter.\r
1481 //\r
1482 case EfiSmbusReadWord:\r
1483 case EfiSmbusWriteWord:\r
1484 case EfiSmbusProcessCall:\r
1485 if (Buffer == NULL || Length == NULL) {\r
1486 return EFI_INVALID_PARAMETER;\r
1487 } else if (*Length < RequiredLen) {\r
1488 Status = EFI_BUFFER_TOO_SMALL;\r
1489 }\r
1490 *Length = RequiredLen;\r
1491 break;\r
1492 case EfiSmbusReadBlock:\r
1493 case EfiSmbusWriteBlock:\r
1494 case EfiSmbusBWBRProcessCall:\r
3a03e95e
SZ
1495 if ((Buffer == NULL) ||\r
1496 (Length == NULL) ||\r
2a956f74
SZ
1497 (*Length < MIN_SMBUS_BLOCK_LEN) ||\r
1498 (*Length > MAX_SMBUS_BLOCK_LEN)) {\r
1499 return EFI_INVALID_PARAMETER;\r
1500 }\r
1501 break;\r
1502 default:\r
1503 return EFI_INVALID_PARAMETER;\r
1504 }\r
1505 return Status;\r
1506}\r
1507\r
64d14edf 1508/**\r
1509 Adds a record for an SMBus command execution into a specified boot script table.\r
1510\r
1511 @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.\r
1512 @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus\r
1513 transactions.\r
1514 @param Length A pointer to signify the number of bytes that this operation will do.\r
1515 @param Buffer Contains the value of data to execute to the SMBUS slave device.\r
3a03e95e 1516\r
64d14edf 1517 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1518 @retval RETURN_SUCCESS Opcode is added.\r
1519**/\r
1520RETURN_STATUS\r
1521EFIAPI\r
1522S3BootScriptSaveSmbusExecute (\r
3a03e95e 1523 IN UINTN SmBusAddress,\r
64d14edf 1524 IN EFI_SMBUS_OPERATION Operation,\r
1525 IN UINTN *Length,\r
1526 IN VOID *Buffer\r
1527 )\r
1528{\r
2a956f74
SZ
1529 EFI_STATUS Status;\r
1530 UINTN BufferLength;\r
64d14edf 1531 UINT8 DataSize;\r
1532 UINT8 *Script;\r
1533 EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute;\r
1534\r
2a956f74
SZ
1535 if (Length == NULL) {\r
1536 BufferLength = 0;\r
1537 } else {\r
1538 BufferLength = *Length;\r
1539 }\r
1540\r
1541 Status = CheckParameters (SmBusAddress, Operation, &BufferLength, Buffer);\r
1542 if (EFI_ERROR (Status)) {\r
1543 return Status;\r
1544 }\r
1545\r
1546 DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + BufferLength);\r
3a03e95e 1547\r
64d14edf 1548 Script = S3BootScriptGetEntryAddAddress (DataSize);\r
1549 if (Script == NULL) {\r
1550 return RETURN_OUT_OF_RESOURCES;\r
1551 }\r
1552 //\r
1553 // Build script data\r
1554 //\r
1555 ScriptSmbusExecute.OpCode = EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE;\r
1556 ScriptSmbusExecute.Length = DataSize;\r
1557 ScriptSmbusExecute.SmBusAddress = (UINT64) SmBusAddress;\r
1558 ScriptSmbusExecute.Operation = Operation;\r
2a956f74 1559 ScriptSmbusExecute.DataSize = (UINT32) BufferLength;\r
64d14edf 1560\r
1561 CopyMem ((VOID*)Script, (VOID*)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));\r
1562 CopyMem (\r
1563 (VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),\r
1564 Buffer,\r
2a956f74 1565 BufferLength\r
64d14edf 1566 );\r
1567\r
02f49fc2 1568 SyncBootScript (Script);\r
64d14edf 1569\r
1570 return RETURN_SUCCESS;\r
1571}\r
1572/**\r
1573 Adds a record for an execution stall on the processor into a specified boot script table.\r
1574\r
1575 @param Duration Duration in microseconds of the stall\r
3a03e95e 1576\r
64d14edf 1577 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1578 @retval RETURN_SUCCESS Opcode is added.\r
1579**/\r
1580RETURN_STATUS\r
1581EFIAPI\r
1582S3BootScriptSaveStall (\r
1583 IN UINTN Duration\r
1584 )\r
1585{\r
1586 UINT8 Length;\r
1587 UINT8 *Script;\r
1588 EFI_BOOT_SCRIPT_STALL ScriptStall;\r
1589\r
1590 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_STALL));\r
3a03e95e 1591\r
64d14edf 1592 Script = S3BootScriptGetEntryAddAddress (Length);\r
1593 if (Script == NULL) {\r
1594 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1595 }\r
64d14edf 1596 //\r
1597 // Build script data\r
1598 //\r
1599 ScriptStall.OpCode = EFI_BOOT_SCRIPT_STALL_OPCODE;\r
1600 ScriptStall.Length = Length;\r
1601 ScriptStall.Duration = Duration;\r
3a03e95e 1602\r
64d14edf 1603 CopyMem ((VOID*)Script, (VOID*)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));\r
3a03e95e 1604\r
02f49fc2 1605 SyncBootScript (Script);\r
64d14edf 1606\r
1607 return RETURN_SUCCESS;\r
1608}\r
1609/**\r
02f49fc2 1610 Adds a record for dispatching specified arbitrary code into a specified boot script table.\r
64d14edf 1611\r
1612 @param EntryPoint Entry point of the code to be dispatched.\r
1613 @param Context Argument to be passed into the EntryPoint of the code to be dispatched.\r
3a03e95e 1614\r
64d14edf 1615 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1616 @retval RETURN_SUCCESS Opcode is added.\r
1617**/\r
1618RETURN_STATUS\r
1619EFIAPI\r
1620S3BootScriptSaveDispatch2 (\r
1621 IN VOID *EntryPoint,\r
1622 IN VOID *Context\r
1623 )\r
1624{\r
1625 UINT8 Length;\r
1626 UINT8 *Script;\r
1627 EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;\r
1628 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));\r
3a03e95e 1629\r
64d14edf 1630 Script = S3BootScriptGetEntryAddAddress (Length);\r
1631 if (Script == NULL) {\r
1632 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1633 }\r
64d14edf 1634 //\r
1635 // Build script data\r
1636 //\r
1637 ScriptDispatch2.OpCode = EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE;\r
1638 ScriptDispatch2.Length = Length;\r
1639 ScriptDispatch2.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;\r
1640 ScriptDispatch2.Context = (EFI_PHYSICAL_ADDRESS)(UINTN)Context;\r
3a03e95e 1641\r
64d14edf 1642 CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));\r
3a03e95e 1643\r
02f49fc2 1644 SyncBootScript (Script);\r
64d14edf 1645\r
1646 return RETURN_SUCCESS;\r
1647\r
1648}\r
1649/**\r
1650 Adds a record for memory reads of the memory location and continues when the exit criteria is\r
1651 satisfied or after a defined duration.\r
57a1b9c4
JY
1652\r
1653 Please aware, below interface is different with PI specification, Vol 5:\r
1654 EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.\r
1655 "Duration" below is microseconds, while "Delay" in PI specification means\r
1656 the number of 100ns units to poll.\r
1657\r
64d14edf 1658 @param Width The width of the memory operations.\r
1659 @param Address The base address of the memory operations.\r
1660 @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.\r
1661 @param BitValue A pointer to the data value after to be Masked.\r
1662 @param Duration Duration in microseconds of the stall.\r
1663 @param LoopTimes The times of the register polling.\r
1664\r
1665 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1666 @retval RETURN_SUCCESS Opcode is added.\r
1667\r
1668**/\r
1669RETURN_STATUS\r
1670EFIAPI\r
1671S3BootScriptSaveMemPoll (\r
1672 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1673 IN UINT64 Address,\r
1674 IN VOID *BitMask,\r
1675 IN VOID *BitValue,\r
1676 IN UINTN Duration,\r
1677 IN UINTN LoopTimes\r
1678 )\r
1679{\r
1680 UINT8 Length;\r
1681 UINT8 *Script;\r
3a03e95e
SZ
1682 UINT8 WidthInByte;\r
1683 EFI_BOOT_SCRIPT_MEM_POLL ScriptMemPoll;\r
64d14edf 1684\r
1685 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
3a03e95e 1686\r
64d14edf 1687 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + (WidthInByte * 2));\r
3a03e95e 1688\r
64d14edf 1689 Script = S3BootScriptGetEntryAddAddress (Length);\r
1690 if (Script == NULL) {\r
1691 return RETURN_OUT_OF_RESOURCES;\r
1692 }\r
1693 //\r
1694 // Build script data\r
1695 //\r
1696 ScriptMemPoll.OpCode = EFI_BOOT_SCRIPT_MEM_POLL_OPCODE;\r
1697 ScriptMemPoll.Length = Length;\r
3a03e95e 1698 ScriptMemPoll.Width = Width;\r
64d14edf 1699 ScriptMemPoll.Address = Address;\r
1700 ScriptMemPoll.Duration = Duration;\r
1701 ScriptMemPoll.LoopTimes = LoopTimes;\r
1702\r
1703 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL)), BitValue, WidthInByte);\r
1704 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);\r
3a03e95e 1705 CopyMem ((VOID*)Script, (VOID*)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL));\r
64d14edf 1706\r
02f49fc2 1707 SyncBootScript (Script);\r
64d14edf 1708\r
1709 return RETURN_SUCCESS;\r
1710}\r
1711/**\r
1712 Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only\r
1713 used for debugging script issues.\r
3a03e95e 1714\r
64d14edf 1715 @param InformationLength Length of the data in bytes\r
1716 @param Information Information to be logged in the boot scrpit\r
3a03e95e 1717\r
64d14edf 1718 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1719 @retval RETURN_SUCCESS Opcode is added.\r
1720\r
1721**/\r
1722RETURN_STATUS\r
1723EFIAPI\r
1724S3BootScriptSaveInformation (\r
3a03e95e 1725 IN UINT32 InformationLength,\r
64d14edf 1726 IN VOID *Information\r
1727 )\r
1728{\r
64d14edf 1729 UINT8 Length;\r
1730 UINT8 *Script;\r
64d14edf 1731 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;\r
1732\r
93b21ade
SZ
1733 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);\r
1734\r
64d14edf 1735 Script = S3BootScriptGetEntryAddAddress (Length);\r
1736 if (Script == NULL) {\r
1737 return RETURN_OUT_OF_RESOURCES;\r
1738 }\r
1739 //\r
1740 // Build script data\r
1741 //\r
1742 ScriptInformation.OpCode = EFI_BOOT_SCRIPT_INFORMATION_OPCODE;\r
1743 ScriptInformation.Length = Length;\r
1744\r
1745\r
3a03e95e 1746 ScriptInformation.InformationLength = InformationLength;\r
64d14edf 1747\r
93b21ade
SZ
1748 CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
1749 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);\r
1750\r
02f49fc2 1751 SyncBootScript (Script);\r
93b21ade 1752\r
64d14edf 1753 return RETURN_SUCCESS;\r
1754\r
1755}\r
1756/**\r
1757 Store a string in the boot script table. This opcode is a no-op on dispatch and is only\r
1758 used for debugging script issues.\r
3a03e95e 1759\r
64d14edf 1760 @param String The string to save to boot script table\r
3a03e95e 1761\r
64d14edf 1762 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1763 @retval RETURN_SUCCESS Opcode is added.\r
1764\r
1765**/\r
1766RETURN_STATUS\r
1767EFIAPI\r
1768S3BootScriptSaveInformationAsciiString (\r
1769 IN CONST CHAR8 *String\r
1770 )\r
1771{\r
3a03e95e
SZ
1772 return S3BootScriptSaveInformation (\r
1773 (UINT32) AsciiStrLen (String) + 1,\r
64d14edf 1774 (VOID*) String\r
1775 );\r
1776}\r
1777/**\r
1778 Adds a record for dispatching specified arbitrary code into a specified boot script table.\r
1779\r
1780 @param EntryPoint Entry point of the code to be dispatched.\r
3a03e95e 1781\r
64d14edf 1782 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1783 @retval RETURN_SUCCESS Opcode is added.\r
1784**/\r
1785RETURN_STATUS\r
1786EFIAPI\r
1787S3BootScriptSaveDispatch (\r
1788 IN VOID *EntryPoint\r
1789 )\r
1790{\r
1791 UINT8 Length;\r
1792 UINT8 *Script;\r
1793 EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;\r
3a03e95e 1794\r
64d14edf 1795 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH));\r
3a03e95e 1796\r
64d14edf 1797 Script = S3BootScriptGetEntryAddAddress (Length);\r
1798 if (Script == NULL) {\r
1799 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1800 }\r
64d14edf 1801 //\r
1802 // Build script data\r
1803 //\r
1804 ScriptDispatch.OpCode = EFI_BOOT_SCRIPT_DISPATCH_OPCODE;\r
1805 ScriptDispatch.Length = Length;\r
1806 ScriptDispatch.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;\r
3a03e95e
SZ
1807\r
1808 CopyMem ((VOID*)Script, (VOID*)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH));\r
1809\r
02f49fc2 1810 SyncBootScript (Script);\r
64d14edf 1811\r
1812 return RETURN_SUCCESS;\r
1813\r
1814}\r
1815/**\r
1816 Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a\r
1817 defined duration.\r
3a03e95e
SZ
1818\r
1819 @param Width The width of the I/O operations.\r
64d14edf 1820 @param Address The base address of the I/O operations.\r
1821 @param Data The comparison value used for the polling exit criteria.\r
1822 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero\r
1823 in Data are ignored when polling the memory address.\r
1824 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer\r
1825 granularity so the delay may be longer.\r
1826\r
1827 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1828 @retval RETURN_SUCCESS Opcode is added.\r
1829\r
1830**/\r
1831RETURN_STATUS\r
1832EFIAPI\r
1833S3BootScriptSaveIoPoll (\r
1834 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1835 IN UINT64 Address,\r
1836 IN VOID *Data,\r
3a03e95e
SZ
1837 IN VOID *DataMask,\r
1838 IN UINT64 Delay\r
64d14edf 1839 )\r
1840{\r
3a03e95e 1841 UINT8 WidthInByte;\r
64d14edf 1842 UINT8 *Script;\r
1843 UINT8 Length;\r
1844 EFI_BOOT_SCRIPT_IO_POLL ScriptIoPoll;\r
64d14edf 1845\r
3a03e95e
SZ
1846\r
1847 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
64d14edf 1848 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));\r
3a03e95e 1849\r
64d14edf 1850 Script = S3BootScriptGetEntryAddAddress (Length);\r
1851 if (Script == NULL) {\r
1852 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1853 }\r
64d14edf 1854 //\r
1855 // Build script data\r
1856 //\r
1857 ScriptIoPoll.OpCode = EFI_BOOT_SCRIPT_IO_POLL_OPCODE;\r
1858 ScriptIoPoll.Length = (UINT8) (sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));\r
3a03e95e 1859 ScriptIoPoll.Width = Width;\r
64d14edf 1860 ScriptIoPoll.Address = Address;\r
1861 ScriptIoPoll.Delay = Delay;\r
1862\r
3a03e95e 1863 CopyMem ((VOID*)Script, (VOID*)&ScriptIoPoll, sizeof (EFI_BOOT_SCRIPT_IO_POLL));\r
64d14edf 1864 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);\r
1865 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);\r
3a03e95e 1866\r
02f49fc2 1867 SyncBootScript (Script);\r
64d14edf 1868\r
1869 return RETURN_SUCCESS;\r
1870}\r
1871\r
1872/**\r
1873 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or\r
1874 after a defined duration.\r
1875\r
3a03e95e 1876 @param Width The width of the I/O operations.\r
64d14edf 1877 @param Address The address within the PCI configuration space.\r
1878 @param Data The comparison value used for the polling exit criteria.\r
1879 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero\r
1880 in Data are ignored when polling the memory address\r
1881 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer\r
1882 granularity so the delay may be longer.\r
1883\r
1884 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1885 @retval RETURN_SUCCESS Opcode is added.\r
2a956f74 1886 @note A known Limitations in the implementation which is 64bits operations are not supported.\r
64d14edf 1887\r
1888**/\r
1889RETURN_STATUS\r
1890EFIAPI\r
1891S3BootScriptSavePciPoll (\r
1892 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1893 IN UINT64 Address,\r
1894 IN VOID *Data,\r
1895 IN VOID *DataMask,\r
1896 IN UINT64 Delay\r
1897)\r
1898{\r
1899 UINT8 *Script;\r
3a03e95e 1900 UINT8 WidthInByte;\r
64d14edf 1901 UINT8 Length;\r
1902 EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll;\r
1903\r
2a956f74
SZ
1904 if (Width == S3BootScriptWidthUint64 ||\r
1905 Width == S3BootScriptWidthFifoUint64 ||\r
1906 Width == S3BootScriptWidthFillUint64) {\r
1907 return EFI_INVALID_PARAMETER;\r
1908 }\r
1909\r
64d14edf 1910 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1911 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));\r
3a03e95e 1912\r
64d14edf 1913 Script = S3BootScriptGetEntryAddAddress (Length);\r
1914 if (Script == NULL) {\r
1915 return RETURN_OUT_OF_RESOURCES;\r
1916 }\r
1917 //\r
1918 // Build script data\r
1919 //\r
1920 ScriptPciPoll.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE;\r
1921 ScriptPciPoll.Length = (UINT8) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));\r
3a03e95e 1922 ScriptPciPoll.Width = Width;\r
64d14edf 1923 ScriptPciPoll.Address = Address;\r
1924 ScriptPciPoll.Delay = Delay;\r
1925\r
1926 CopyMem ((VOID*)Script, (VOID*)&ScriptPciPoll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));\r
1927 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);\r
1928 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);\r
3a03e95e 1929\r
02f49fc2 1930 SyncBootScript (Script);\r
64d14edf 1931\r
1932 return RETURN_SUCCESS;\r
1933}\r
1934/**\r
1935 Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or\r
1936 after a defined duration.\r
1937\r
3a03e95e 1938 @param Width The width of the I/O operations.\r
64d14edf 1939 @param Segment The PCI segment number for Address.\r
1940 @param Address The address within the PCI configuration space.\r
1941 @param Data The comparison value used for the polling exit criteria.\r
1942 @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero\r
1943 in Data are ignored when polling the memory address\r
1944 @param Delay The number of 100ns units to poll. Note that timer available may be of poorer\r
1945 granularity so the delay may be longer.\r
1946\r
1947 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
1948 @retval RETURN_SUCCESS Opcode is added.\r
2a956f74
SZ
1949 @note A known Limitations in the implementation which is non-zero Segment and 64bits operations are not supported.\r
1950\r
64d14edf 1951**/\r
1952RETURN_STATUS\r
1953EFIAPI\r
1954S3BootScriptSavePci2Poll (\r
1955 IN S3_BOOT_SCRIPT_LIB_WIDTH Width,\r
1956 IN UINT16 Segment,\r
1957 IN UINT64 Address,\r
1958 IN VOID *Data,\r
1959 IN VOID *DataMask,\r
1960 IN UINT64 Delay\r
1961)\r
1962{\r
3a03e95e 1963 UINT8 WidthInByte;\r
64d14edf 1964 UINT8 *Script;\r
1965 UINT8 Length;\r
1966 EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll;\r
2a956f74
SZ
1967\r
1968 if (Segment != 0 ||\r
1969 Width == S3BootScriptWidthUint64 ||\r
1970 Width == S3BootScriptWidthFifoUint64 ||\r
1971 Width == S3BootScriptWidthFillUint64) {\r
1972 return EFI_INVALID_PARAMETER;\r
1973 }\r
1974\r
64d14edf 1975 WidthInByte = (UINT8) (0x01 << (Width & 0x03));\r
1976 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));\r
3a03e95e 1977\r
64d14edf 1978 Script = S3BootScriptGetEntryAddAddress (Length);\r
1979 if (Script == NULL) {\r
1980 return RETURN_OUT_OF_RESOURCES;\r
3a03e95e 1981 }\r
64d14edf 1982 //\r
1983 // Build script data\r
1984 //\r
1985 ScriptPci2Poll.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE;\r
1986 ScriptPci2Poll.Length = (UINT8) (sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));\r
3a03e95e 1987 ScriptPci2Poll.Width = Width;\r
64d14edf 1988 ScriptPci2Poll.Segment = Segment;\r
1989 ScriptPci2Poll.Address = Address;\r
1990 ScriptPci2Poll.Delay = Delay;\r
1991\r
1992 CopyMem ((VOID*)Script, (VOID*)&ScriptPci2Poll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));\r
1993 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);\r
1994 CopyMem ((UINT8 *) (Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);\r
3a03e95e 1995\r
02f49fc2 1996 SyncBootScript (Script);\r
64d14edf 1997\r
1998 return RETURN_SUCCESS;\r
1999}\r
2000/**\r
2001 Do the calculation of start address from which a new s3 boot script entry will write into.\r
3a03e95e 2002\r
64d14edf 2003 @param EntryLength The new entry length.\r
2004 @param Position specifies the position in the boot script table where the opcode will be\r
3a03e95e 2005 inserted, either before or after, depending on BeforeOrAfter.\r
64d14edf 2006 @param BeforeOrAfter The flag to indicate to insert the nod before or after the position.\r
2007 This parameter is effective when InsertFlag is TRUE\r
2008 @param Script return out the position from which the a new s3 boot script entry will write into\r
2009**/\r
2010VOID\r
2011S3BootScriptCalculateInsertAddress (\r
2012 IN UINT8 EntryLength,\r
2013 IN VOID *Position OPTIONAL,\r
2014 IN BOOLEAN BeforeOrAfter OPTIONAL,\r
3a03e95e 2015 OUT UINT8 **Script\r
64d14edf 2016 )\r
2017{\r
2018 UINTN TableLength;\r
2019 UINT8 *S3TableBase;\r
3a03e95e 2020 UINTN PositionOffset;\r
64d14edf 2021 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;\r
2022 //\r
2023 // The entry inserting to table is already added to the end of the table\r
2024 //\r
2025 TableLength = mS3BootScriptTablePtr->TableLength - EntryLength;\r
2026 S3TableBase = mS3BootScriptTablePtr->TableBase ;\r
3a03e95e 2027 //\r
64d14edf 2028 // calculate the Position offset\r
2029 //\r
2030 if (Position != NULL) {\r
2031 PositionOffset = (UINTN) ((UINT8 *)Position - S3TableBase);\r
3a03e95e 2032\r
64d14edf 2033 //\r
2034 // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.\r
2035 //\r
2036 if (!BeforeOrAfter) {\r
3a03e95e 2037 CopyMem ((VOID*)&ScriptHeader, Position, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
64d14edf 2038 PositionOffset += (ScriptHeader.Length);\r
2039 }\r
3a03e95e 2040 //\r
64d14edf 2041 // Insert the node before the adjusted Position\r
2042 //\r
3a03e95e 2043 CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);\r
64d14edf 2044 //\r
3a03e95e 2045 // calculate the the start address for the new entry.\r
64d14edf 2046 //\r
2047 *Script = S3TableBase + PositionOffset;\r
3a03e95e 2048\r
64d14edf 2049 } else {\r
2050 if (!BeforeOrAfter) {\r
2051 //\r
2052 // Insert the node to the end of the table\r
2053 //\r
3a03e95e 2054 *Script = S3TableBase + TableLength;\r
64d14edf 2055 } else {\r
3a03e95e 2056 //\r
64d14edf 2057 // Insert the node to the beginning of the table\r
2058 //\r
2059 PositionOffset = (UINTN) sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);\r
3a03e95e
SZ
2060 CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);\r
2061 *Script = S3TableBase + PositionOffset;\r
64d14edf 2062 }\r
3a03e95e 2063 }\r
64d14edf 2064}\r
2065/**\r
3a03e95e 2066 Move the last boot script entry to the position\r
64d14edf 2067\r
2068 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position\r
2069 in the boot script table specified by Position. If Position is NULL or points to\r
2070 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end\r
2071 of the table (if FALSE).\r
2072 @param Position On entry, specifies the position in the boot script table where the opcode will be\r
2073 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies\r
2074 the position of the inserted opcode in the boot script table.\r
2075\r
2076 @retval RETURN_OUT_OF_RESOURCES The table is not available.\r
2077 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.\r
2078 @retval RETURN_SUCCESS Opcode is inserted.\r
2079**/\r
2080RETURN_STATUS\r
2081EFIAPI\r
2082S3BootScriptMoveLastOpcode (\r
2083 IN BOOLEAN BeforeOrAfter,\r
2084 IN OUT VOID **Position OPTIONAL\r
2085)\r
2086{\r
2087 UINT8* Script;\r
3a03e95e 2088 VOID *TempPosition;\r
64d14edf 2089 UINTN StartAddress;\r
2090 UINT32 TableLength;\r
2091 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;\r
2092 BOOLEAN ValidatePosition;\r
2093 UINT8* LastOpcode;\r
2094 UINT8 TempBootScriptEntry[BOOT_SCRIPT_NODE_MAX_LENGTH];\r
3a03e95e 2095\r
64d14edf 2096 ValidatePosition = FALSE;\r
2097 TempPosition = (Position == NULL) ? NULL:(*Position);\r
02f49fc2
SZ
2098\r
2099 //\r
2100 // Check that the script is initialized and synced without adding an entry to the script.\r
2101 //\r
2102 Script = S3BootScriptGetEntryAddAddress (0);\r
2103 if (Script == NULL) {\r
2104 return RETURN_OUT_OF_RESOURCES;\r
64d14edf 2105 }\r
02f49fc2
SZ
2106 Script = mS3BootScriptTablePtr->TableBase;\r
2107\r
64d14edf 2108 StartAddress = (UINTN) Script;\r
2109 TableLength = mS3BootScriptTablePtr->TableLength;\r
2110 Script = Script + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER);\r
2111 LastOpcode = Script;\r
2112 //\r
2113 // Find the last boot Script Entry which is not the terminate node\r
2114 //\r
3a03e95e
SZ
2115 while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {\r
2116 CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
64d14edf 2117 if (TempPosition != NULL && TempPosition == Script) {\r
2118 //\r
3a03e95e 2119 // If the position is specified, the position must be pointed to a boot script entry start address.\r
64d14edf 2120 //\r
2121 ValidatePosition = TRUE;\r
2122 }\r
2123 if (ScriptHeader.OpCode != S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE) {\r
2124 LastOpcode = Script;\r
3a03e95e 2125 }\r
64d14edf 2126 Script = Script + ScriptHeader.Length;\r
2127 }\r
2128 //\r
2129 // If the position is specified, but not the start of a boot script entry, it is a invalid input\r
2130 //\r
2131 if (TempPosition != NULL && !ValidatePosition) {\r
2132 return RETURN_INVALID_PARAMETER;\r
2133 }\r
3a03e95e
SZ
2134\r
2135 CopyMem ((VOID*)&ScriptHeader, LastOpcode, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
2136\r
2137 CopyMem((VOID*)TempBootScriptEntry, LastOpcode, ScriptHeader.Length);\r
64d14edf 2138 //\r
2139 // Find the right position to write the node in\r
2140 //\r
2141 S3BootScriptCalculateInsertAddress (\r
2142 ScriptHeader.Length,\r
2143 TempPosition,\r
2144 BeforeOrAfter,\r
3a03e95e 2145 &Script\r
64d14edf 2146 );\r
2147 //\r
2148 // Copy the node to Boot script table\r
2149 //\r
02f49fc2
SZ
2150 CopyMem((VOID*)Script, (VOID*)TempBootScriptEntry, ScriptHeader.Length);\r
2151\r
2152 SyncBootScript (Script);\r
2153\r
64d14edf 2154 //\r
2155 // return out the Position\r
2156 //\r
2157 if (Position != NULL) {\r
2158 *Position = Script;\r
2159 }\r
2160 return RETURN_SUCCESS;\r
2161}\r
2162/**\r
3a03e95e
SZ
2163 Create a Label node in the boot script table.\r
2164\r
64d14edf 2165 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position\r
2166 in the boot script table specified by Position. If Position is NULL or points to\r
2167 NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end\r
2168 of the table (if FALSE).\r
2169 @param Position On entry, specifies the position in the boot script table where the opcode will be\r
2170 inserted, either before or after, depending on BeforeOrAfter. On exit, specifies\r
3a03e95e 2171 the position of the inserted opcode in the boot script table.\r
64d14edf 2172 @param InformationLength Length of the label in bytes\r
2173 @param Information Label to be logged in the boot scrpit\r
3a03e95e 2174\r
64d14edf 2175 @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.\r
2176 @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.\r
2177 @retval RETURN_SUCCESS Opcode is added.\r
2178\r
2179**/\r
2180RETURN_STATUS\r
2181EFIAPI\r
2182S3BootScriptLabelInternal (\r
2183 IN BOOLEAN BeforeOrAfter,\r
3a03e95e
SZ
2184 IN OUT VOID **Position OPTIONAL,\r
2185 IN UINT32 InformationLength,\r
64d14edf 2186 IN CONST CHAR8 *Information\r
2187 )\r
2188{\r
2189 UINT8 Length;\r
2190 UINT8 *Script;\r
64d14edf 2191 EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;\r
3a03e95e 2192\r
64d14edf 2193 Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);\r
3a03e95e 2194\r
64d14edf 2195 Script = S3BootScriptGetEntryAddAddress (Length);\r
2196 if (Script == NULL) {\r
2197 return RETURN_OUT_OF_RESOURCES;\r
2198 }\r
64d14edf 2199 //\r
2200 // Build script data\r
2201 //\r
2202 ScriptInformation.OpCode = S3_BOOT_SCRIPT_LIB_LABEL_OPCODE;\r
2203 ScriptInformation.Length = Length;\r
2204\r
2205\r
3a03e95e 2206 ScriptInformation.InformationLength = InformationLength;\r
64d14edf 2207\r
93b21ade
SZ
2208 CopyMem ((VOID*)Script, (VOID*)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));\r
2209 CopyMem ((VOID*)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *) Information, (UINTN) InformationLength);\r
2210\r
02f49fc2
SZ
2211 SyncBootScript (Script);\r
2212\r
64d14edf 2213 return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);\r
2214\r
2215}\r
2216/**\r
2217 Find a label within the boot script table and, if not present, optionally create it.\r
2218\r
2219 @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE)\r
3a03e95e 2220 or after (FALSE) the position in the boot script table\r
64d14edf 2221 specified by Position.\r
3a03e95e 2222 @param CreateIfNotFound Specifies whether the label will be created if the label\r
64d14edf 2223 does not exists (TRUE) or not (FALSE).\r
2224 @param Position On entry, specifies the position in the boot script table\r
2225 where the opcode will be inserted, either before or after,\r
2226 depending on BeforeOrAfter. On exit, specifies the position\r
2227 of the inserted opcode in the boot script table.\r
2228 @param Label Points to the label which will be inserted in the boot script table.\r
2229\r
2230 @retval EFI_SUCCESS The operation succeeded. A record was added into the\r
2231 specified script table.\r
2232 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.\r
3a03e95e 2233 If the opcode is unknow or not supported because of the PCD\r
64d14edf 2234 Feature Flags.\r
2235 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.\r
2236\r
2237**/\r
2238RETURN_STATUS\r
3a03e95e 2239EFIAPI\r
64d14edf 2240S3BootScriptLabel (\r
2241 IN BOOLEAN BeforeOrAfter,\r
2242 IN BOOLEAN CreateIfNotFound,\r
2243 IN OUT VOID **Position OPTIONAL,\r
2244 IN CONST CHAR8 *Label\r
2245 )\r
2246{\r
2247 UINT8* Script;\r
2248 UINTN StartAddress;\r
2249 UINT32 TableLength;\r
2250 EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;\r
2251 EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;\r
2252 UINT32 LabelLength;\r
2253 //\r
96072947 2254 // Check NULL Label\r
64d14edf 2255 //\r
96072947
JY
2256 if (Label == NULL) {\r
2257 return EFI_INVALID_PARAMETER;\r
2258 }\r
2259 //\r
2260 // Check empty Label\r
2261 //\r
2262 if (Label[0] == '\0') {\r
64d14edf 2263 return EFI_INVALID_PARAMETER;\r
2264 }\r
3a03e95e 2265\r
64d14edf 2266 //\r
02f49fc2
SZ
2267 // Check that the script is initialized and synced without adding an entry to the script.\r
2268 // The code must search for the label first before it knows if a new entry needs\r
64d14edf 2269 // to be added.\r
2270 //\r
2271 Script = S3BootScriptGetEntryAddAddress (0);\r
2272 if (Script == NULL) {\r
2273 return RETURN_OUT_OF_RESOURCES;\r
2274 }\r
3a03e95e 2275\r
64d14edf 2276 //\r
2277 // Check the header and search for existing label.\r
3a03e95e 2278 //\r
64d14edf 2279 Script = mS3BootScriptTablePtr->TableBase;\r
2280 CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));\r
2281 if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {\r
2282 return EFI_INVALID_PARAMETER;\r
2283 }\r
2284 StartAddress = (UINTN) Script;\r
2285 TableLength = mS3BootScriptTablePtr->TableLength;\r
2286 Script = Script + TableHeader.Length;\r
2287 while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {\r
3a03e95e
SZ
2288\r
2289 CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));\r
64d14edf 2290 if (ScriptHeader.OpCode == S3_BOOT_SCRIPT_LIB_LABEL_OPCODE) {\r
2291 if (AsciiStrCmp ((CHAR8 *)(UINTN)(Script+sizeof(EFI_BOOT_SCRIPT_INFORMATION)), Label) == 0) {\r
3a03e95e 2292 (*Position) = Script;\r
64d14edf 2293 return EFI_SUCCESS;\r
2294 }\r
3a03e95e 2295 }\r
64d14edf 2296 Script = Script + ScriptHeader.Length;\r
2297 }\r
2298 if (CreateIfNotFound) {\r
2299 LabelLength = (UINT32)AsciiStrSize(Label);\r
3a03e95e 2300 return S3BootScriptLabelInternal (BeforeOrAfter,Position, LabelLength, Label);\r
64d14edf 2301 } else {\r
2302 return EFI_NOT_FOUND;\r
3a03e95e 2303 }\r
64d14edf 2304}\r
2305\r
2306/**\r
2307 Compare two positions in the boot script table and return their relative position.\r
2308 @param Position1 The positions in the boot script table to compare\r
2309 @param Position2 The positions in the boot script table to compare\r
2310 @param RelativePosition On return, points to the result of the comparison\r
2311\r
2312 @retval EFI_SUCCESS The operation succeeded. A record was added into the\r
2313 specified script table.\r
2314 @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.\r
3a03e95e 2315 If the opcode is unknow or not supported because of the PCD\r
64d14edf 2316 Feature Flags.\r
2317 @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.\r
2318\r
2319**/\r
2320RETURN_STATUS\r
3a03e95e 2321EFIAPI\r
64d14edf 2322S3BootScriptCompare (\r
2323 IN UINT8 *Position1,\r
2324 IN UINT8 *Position2,\r
2325 OUT UINTN *RelativePosition\r
2326 )\r
2327{\r
2328 UINT8* Script;\r
3a03e95e 2329 UINT32 TableLength;\r
64d14edf 2330\r
64d14edf 2331 if (RelativePosition == NULL) {\r
2332 return EFI_INVALID_PARAMETER;\r
2333 }\r
02f49fc2
SZ
2334\r
2335 //\r
2336 // Check that the script is initialized and synced without adding an entry to the script.\r
2337 //\r
2338 Script = S3BootScriptGetEntryAddAddress (0);\r
2339 if (Script == NULL) {\r
2340 return RETURN_OUT_OF_RESOURCES;\r
2341 }\r
2342 Script = mS3BootScriptTablePtr->TableBase;\r
2343\r
64d14edf 2344 //\r
879dbe18 2345 // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up\r
64d14edf 2346 //\r
879dbe18 2347 TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);\r
64d14edf 2348 if (Position1 < Script || Position1 > Script+TableLength) {\r
2349 return EFI_INVALID_PARAMETER;\r
2350 }\r
2351 if (Position2 < Script || Position2 > Script+TableLength) {\r
2352 return EFI_INVALID_PARAMETER;\r
2353 }\r
2354 *RelativePosition = (Position1 < Position2)?-1:((Position1 == Position2)?0:1);\r
3a03e95e 2355\r
64d14edf 2356 return EFI_SUCCESS;\r
2357}\r
2358\r