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