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