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