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