1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578 |
- /** @file
- Save the S3 data to S3 boot script.
- Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "InternalBootScriptLib.h"
- /**
- Data structure usage:
- +------------------------------+<------- PcdS3BootScriptTablePrivateDataPtr
- | SCRIPT_TABLE_PRIVATE_DATA | (mS3BootScriptTablePtr, Before SmmReadyToLock)
- | TableBase |--- PcdS3BootScriptTablePrivateSmmDataPtr
- | TableLength |--|-- (mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr, After SmmReadyToLock InSmm)
- | TableMemoryPageNumber |--|-|----
- | AtRuntime | | | |
- | InSmm | | | |
- | BootTimeScriptLength |--|-|---|---
- | SmmLocked | | | | |
- | BackFromS3 | | | | |
- +------------------------------+ | | | |
- | | | |
- +------------------------------+<-- | | |
- | EFI_BOOT_SCRIPT_TABLE_HEADER | | | |
- | TableLength |----|-- | |
- +------------------------------+ | | | |
- | ...... | | | | |
- +------------------------------+<---- | | |
- | EFI_BOOT_SCRIPT_TERMINATE | | | |
- +------------------------------+<------ | |
- | |
- | |
- mBootScriptDataBootTimeGuid LockBox: | |
- Used to restore data after back from S3| |
- to handle potential INSERT boot script | |
- at runtime. | |
- +------------------------------+ | |
- | Boot Time Boot Script | | |
- | Before SmmReadyToLock | | |
- | | | |
- | | | |
- +------------------------------+ | |
- | Boot Time Boot Script | | |
- | After SmmReadyToLock InSmm | | |
- | | | |
- +------------------------------+<-------|--|
- | |
- | |
- mBootScriptDataGuid LockBox: (IN_PLACE) | |
- Used to restore data at S3 resume. | |
- +------------------------------+ | |
- | Boot Time Boot Script | | |
- | Before SmmReadyToLock | | |
- | | | |
- | | | |
- +------------------------------+ | |
- | Boot Time Boot Script | | |
- | After SmmReadyToLock InSmm | | |
- | | | |
- +------------------------------+<-------|---
- | Runtime Boot Script | |
- | After SmmReadyToLock InSmm | |
- +------------------------------+ |
- | ...... | |
- +------------------------------+<--------
- mBootScriptTableBaseGuid LockBox: (IN_PLACE)
- +------------------------------+
- | mS3BootScriptTablePtr-> |
- | TableBase |
- +------------------------------+
- mBootScriptSmmPrivateDataGuid LockBox: (IN_PLACE)
- SMM private data with BackFromS3 = TRUE
- at runtime. S3 will help restore it to
- tell the Library the system is back from S3.
- +------------------------------+
- | SCRIPT_TABLE_PRIVATE_DATA |
- | TableBase |
- | TableLength |
- | TableMemoryPageNumber |
- | AtRuntime |
- | InSmm |
- | BootTimeScriptLength |
- | SmmLocked |
- | BackFromS3 = TRUE |
- +------------------------------+
- **/
- SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTablePtr;
- //
- // Allocate SMM copy because we can not use mS3BootScriptTablePtr after SmmReadyToLock in InSmm.
- //
- SCRIPT_TABLE_PRIVATE_DATA *mS3BootScriptTableSmmPtr;
- EFI_GUID mBootScriptDataGuid = {
- 0xaea6b965, 0xdcf5, 0x4311, { 0xb4, 0xb8, 0xf, 0x12, 0x46, 0x44, 0x94, 0xd2 }
- };
- EFI_GUID mBootScriptDataBootTimeGuid = {
- 0xb5af1d7a, 0xb8cf, 0x4eb3, { 0x89, 0x25, 0xa8, 0x20, 0xe1, 0x6b, 0x68, 0x7d }
- };
- EFI_GUID mBootScriptTableBaseGuid = {
- 0x1810ab4a, 0x2314, 0x4df6, { 0x81, 0xeb, 0x67, 0xc6, 0xec, 0x5, 0x85, 0x91 }
- };
- EFI_GUID mBootScriptSmmPrivateDataGuid = {
- 0x627ee2da, 0x3bf9, 0x439b, { 0x92, 0x9f, 0x2e, 0xe, 0x6e, 0x9d, 0xba, 0x62 }
- };
- EFI_EVENT mEventDxeSmmReadyToLock = NULL;
- VOID *mRegistrationSmmExitBootServices = NULL;
- VOID *mRegistrationSmmLegacyBoot = NULL;
- VOID *mRegistrationSmmReadyToLock = NULL;
- BOOLEAN mS3BootScriptTableAllocated = FALSE;
- BOOLEAN mS3BootScriptTableSmmAllocated = FALSE;
- EFI_SMM_SYSTEM_TABLE2 *mBootScriptSmst = NULL;
- BOOLEAN mS3BootScriptAcpiS3Enable = TRUE;
- /**
- This is an internal function to add a terminate node the entry, recalculate the table
- length and fill into the table.
- @return the base address of the boot script table.
- **/
- UINT8 *
- S3BootScriptInternalCloseTable (
- VOID
- )
- {
- UINT8 *S3TableBase;
- EFI_BOOT_SCRIPT_TERMINATE ScriptTerminate;
- EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;
- S3TableBase = mS3BootScriptTablePtr->TableBase;
- if (S3TableBase == NULL) {
- //
- // the table is not exist
- //
- return S3TableBase;
- }
- //
- // Append the termination entry.
- //
- ScriptTerminate.OpCode = S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE;
- ScriptTerminate.Length = (UINT8)sizeof (EFI_BOOT_SCRIPT_TERMINATE);
- CopyMem (mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength, &ScriptTerminate, sizeof (EFI_BOOT_SCRIPT_TERMINATE));
- //
- // fill the table length
- //
- ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER *)(mS3BootScriptTablePtr->TableBase);
- ScriptTableInfo->TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
- return S3TableBase;
- //
- // NOTE: Here we did NOT adjust the mS3BootScriptTablePtr->TableLength to
- // mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE).
- // Because maybe after SmmReadyToLock, we still need add entries into the table,
- // and the entry should be added start before this TERMINATE node.
- //
- }
- /**
- This function save boot script data to LockBox.
- **/
- VOID
- SaveBootScriptDataToLockBox (
- VOID
- )
- {
- EFI_STATUS Status;
- //
- // Save whole memory copy into LockBox.
- // It will be used to restore data at S3 resume.
- //
- Status = SaveLockBox (
- &mBootScriptDataGuid,
- (VOID *)mS3BootScriptTablePtr->TableBase,
- EFI_PAGES_TO_SIZE (mS3BootScriptTablePtr->TableMemoryPageNumber)
- );
- ASSERT_EFI_ERROR (Status);
- Status = SetLockBoxAttributes (&mBootScriptDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
- ASSERT_EFI_ERROR (Status);
- //
- // Just need save TableBase.
- // Do not update other field because they will NOT be used in S3.
- //
- Status = SaveLockBox (
- &mBootScriptTableBaseGuid,
- (VOID *)&mS3BootScriptTablePtr->TableBase,
- sizeof (mS3BootScriptTablePtr->TableBase)
- );
- ASSERT_EFI_ERROR (Status);
- Status = SetLockBoxAttributes (&mBootScriptTableBaseGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
- ASSERT_EFI_ERROR (Status);
- }
- /**
- This is the Event call back function to notify the Library the system is entering
- SmmLocked phase.
- @param Event Pointer to this event
- @param Context Event handler private data
- **/
- VOID
- EFIAPI
- S3BootScriptEventCallBack (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- VOID *Interface;
- //
- // Try to locate it because EfiCreateProtocolNotifyEvent will trigger it once when registration.
- // Just return if it is not found.
- //
- Status = gBS->LocateProtocol (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- NULL,
- &Interface
- );
- if (EFI_ERROR (Status)) {
- return;
- }
- //
- // Here we should tell the library that we are entering SmmLocked phase.
- // and the memory page number occupied by the table should not grow anymore.
- //
- if (!mS3BootScriptTablePtr->SmmLocked) {
- //
- // Before SmmReadyToLock, we need not write the terminate node when adding a node to boot scipt table
- // or else, that will impact the performance. However, after SmmReadyToLock, we should append terminate
- // node on every add to boot script table.
- //
- S3BootScriptInternalCloseTable ();
- mS3BootScriptTablePtr->SmmLocked = TRUE;
- //
- // Save BootScript data to lockbox
- //
- SaveBootScriptDataToLockBox ();
- }
- }
- /**
- This is the Event call back function is triggered in SMM to notify the Library
- the system is entering SmmLocked phase and set InSmm flag.
- @param Protocol Points to the protocol's unique identifier
- @param Interface Points to the interface instance
- @param Handle The handle on which the interface was installed
- @retval EFI_SUCCESS SmmEventCallback runs successfully
- **/
- EFI_STATUS
- EFIAPI
- S3BootScriptSmmEventCallBack (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
- {
- //
- // Check if it is already done
- //
- if (mS3BootScriptTablePtr == mS3BootScriptTableSmmPtr) {
- return EFI_SUCCESS;
- }
- //
- // Last chance to call-out, just make sure SmmLocked is set.
- //
- S3BootScriptEventCallBack (NULL, NULL);
- //
- // Save a SMM copy. If TableBase is NOT null, it means SMM copy has been ready, skip copy mem.
- //
- if (mS3BootScriptTableSmmPtr->TableBase == NULL) {
- CopyMem (mS3BootScriptTableSmmPtr, mS3BootScriptTablePtr, sizeof (*mS3BootScriptTablePtr));
- //
- // Set InSmm, we allow boot script update when InSmm, but not allow boot script outside SMM.
- // InSmm will only be checked if SmmLocked is TRUE.
- //
- mS3BootScriptTableSmmPtr->InSmm = TRUE;
- }
- //
- // We should not use ACPI Reserved copy, because it is not safe.
- //
- mS3BootScriptTablePtr = mS3BootScriptTableSmmPtr;
- return EFI_SUCCESS;
- }
- /**
- This function is to save boot time boot script data to LockBox.
- Because there may be INSERT boot script at runtime in SMM.
- The boot time copy will be used to restore data after back from S3.
- Otherwise the data inserted may cause some boot time boot script data lost
- if only BootScriptData used.
- **/
- VOID
- SaveBootTimeDataToLockBox (
- VOID
- )
- {
- EFI_STATUS Status;
- //
- // ACPI Reserved copy is not safe, restore from BootScriptData LockBox first,
- // and then save the data to BootScriptDataBootTime LockBox.
- //
- Status = RestoreLockBox (
- &mBootScriptDataGuid,
- NULL,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Save BootScriptDataBootTime
- // It will be used to restore data after back from S3.
- //
- Status = SaveLockBox (
- &mBootScriptDataBootTimeGuid,
- (VOID *)mS3BootScriptTablePtr->TableBase,
- mS3BootScriptTablePtr->BootTimeScriptLength
- );
- ASSERT_EFI_ERROR (Status);
- }
- /**
- This function save boot script SMM private data to LockBox with BackFromS3 = TRUE at runtime.
- S3 resume will help restore it to tell the Library the system is back from S3.
- **/
- VOID
- SaveSmmPriviateDataToLockBoxAtRuntime (
- VOID
- )
- {
- EFI_STATUS Status;
- //
- // Save boot script SMM private data with BackFromS3 = TRUE.
- //
- mS3BootScriptTablePtr->BackFromS3 = TRUE;
- Status = SaveLockBox (
- &mBootScriptSmmPrivateDataGuid,
- (VOID *)mS3BootScriptTablePtr,
- sizeof (SCRIPT_TABLE_PRIVATE_DATA)
- );
- ASSERT_EFI_ERROR (Status);
- Status = SetLockBoxAttributes (&mBootScriptSmmPrivateDataGuid, LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE);
- ASSERT_EFI_ERROR (Status);
- //
- // Set BackFromS3 flag back to FALSE to indicate that now is not back from S3.
- //
- mS3BootScriptTablePtr->BackFromS3 = FALSE;
- }
- /**
- This is the Event call back function is triggered in SMM to notify the Library
- the system is entering runtime phase.
- @param[in] Protocol Points to the protocol's unique identifier
- @param[in] Interface Points to the interface instance
- @param[in] Handle The handle on which the interface was installed
- @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
- **/
- EFI_STATUS
- EFIAPI
- S3BootScriptSmmAtRuntimeCallBack (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
- {
- if (!mS3BootScriptTablePtr->AtRuntime) {
- mS3BootScriptTablePtr->BootTimeScriptLength = (UINT32)(mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
- SaveBootTimeDataToLockBox ();
- mS3BootScriptTablePtr->AtRuntime = TRUE;
- SaveSmmPriviateDataToLockBoxAtRuntime ();
- }
- return EFI_SUCCESS;
- }
- /**
- Library Constructor.
- this function just identify it is a smm driver or non-smm driver linked against
- with the library
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
- @retval RETURN_SUCCESS The constructor always returns RETURN_SUCCESS.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptLibInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- SCRIPT_TABLE_PRIVATE_DATA *S3TablePtr;
- SCRIPT_TABLE_PRIVATE_DATA *S3TableSmmPtr;
- VOID *Registration;
- EFI_SMM_BASE2_PROTOCOL *SmmBase2;
- BOOLEAN InSmm;
- EFI_PHYSICAL_ADDRESS Buffer;
- if (!PcdGetBool (PcdAcpiS3Enable)) {
- mS3BootScriptAcpiS3Enable = FALSE;
- DEBUG ((DEBUG_INFO, "%a: Skip S3BootScript because ACPI S3 disabled.\n", gEfiCallerBaseName));
- return RETURN_SUCCESS;
- }
- S3TablePtr = (SCRIPT_TABLE_PRIVATE_DATA *)(UINTN)PcdGet64 (PcdS3BootScriptTablePrivateDataPtr);
- //
- // The Boot script private data is not be initialized. create it
- //
- if (S3TablePtr == 0) {
- Buffer = SIZE_4GB - 1;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- EFI_SIZE_TO_PAGES (sizeof (SCRIPT_TABLE_PRIVATE_DATA)),
- &Buffer
- );
- ASSERT_EFI_ERROR (Status);
- mS3BootScriptTableAllocated = TRUE;
- S3TablePtr = (VOID *)(UINTN)Buffer;
- Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, (UINT64)(UINTN)S3TablePtr);
- ASSERT_EFI_ERROR (Status);
- ZeroMem (S3TablePtr, sizeof (SCRIPT_TABLE_PRIVATE_DATA));
- //
- // Create event to notify the library system enter the SmmLocked phase.
- //
- mEventDxeSmmReadyToLock = EfiCreateProtocolNotifyEvent (
- &gEfiDxeSmmReadyToLockProtocolGuid,
- TPL_CALLBACK,
- S3BootScriptEventCallBack,
- NULL,
- &Registration
- );
- ASSERT (mEventDxeSmmReadyToLock != NULL);
- }
- mS3BootScriptTablePtr = S3TablePtr;
- //
- // Get InSmm, we need to register SmmReadyToLock if this library is linked to SMM driver.
- //
- Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID **)&SmmBase2);
- if (EFI_ERROR (Status)) {
- return RETURN_SUCCESS;
- }
- Status = SmmBase2->InSmm (SmmBase2, &InSmm);
- if (EFI_ERROR (Status)) {
- return RETURN_SUCCESS;
- }
- if (!InSmm) {
- return RETURN_SUCCESS;
- }
- //
- // Good, we are in SMM
- //
- Status = SmmBase2->GetSmstLocation (SmmBase2, &mBootScriptSmst);
- if (EFI_ERROR (Status)) {
- return RETURN_SUCCESS;
- }
- S3TableSmmPtr = (SCRIPT_TABLE_PRIVATE_DATA *)(UINTN)PcdGet64 (PcdS3BootScriptTablePrivateSmmDataPtr);
- //
- // The Boot script private data in SMM is not be initialized. create it
- //
- if (S3TableSmmPtr == 0) {
- Status = mBootScriptSmst->SmmAllocatePool (
- EfiRuntimeServicesData,
- sizeof (SCRIPT_TABLE_PRIVATE_DATA),
- (VOID **)&S3TableSmmPtr
- );
- ASSERT_EFI_ERROR (Status);
- mS3BootScriptTableSmmAllocated = TRUE;
- Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, (UINT64)(UINTN)S3TableSmmPtr);
- ASSERT_EFI_ERROR (Status);
- ZeroMem (S3TableSmmPtr, sizeof (SCRIPT_TABLE_PRIVATE_DATA));
- //
- // Register SmmExitBootServices and SmmLegacyBoot notification.
- //
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmExitBootServicesProtocolGuid,
- S3BootScriptSmmAtRuntimeCallBack,
- &mRegistrationSmmExitBootServices
- );
- ASSERT_EFI_ERROR (Status);
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmLegacyBootProtocolGuid,
- S3BootScriptSmmAtRuntimeCallBack,
- &mRegistrationSmmLegacyBoot
- );
- ASSERT_EFI_ERROR (Status);
- }
- mS3BootScriptTableSmmPtr = S3TableSmmPtr;
- //
- // Register SmmReadyToLock notification.
- //
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEfiSmmReadyToLockProtocolGuid,
- S3BootScriptSmmEventCallBack,
- &mRegistrationSmmReadyToLock
- );
- ASSERT_EFI_ERROR (Status);
- return RETURN_SUCCESS;
- }
- /**
- Library Destructor to free the resources allocated by
- S3BootScriptLibInitialize() and unregister callbacks.
- NOTICE: The destructor doesn't support unloading as a separate action, and it
- only supports unloading if the containing driver's entry point function fails.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
- @retval RETURN_SUCCESS The destructor always returns RETURN_SUCCESS.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptLibDeinitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- DEBUG ((DEBUG_INFO, "%a() in %a module\n", __FUNCTION__, gEfiCallerBaseName));
- if (mEventDxeSmmReadyToLock != NULL) {
- //
- // Close the DxeSmmReadyToLock event.
- //
- Status = gBS->CloseEvent (mEventDxeSmmReadyToLock);
- ASSERT_EFI_ERROR (Status);
- }
- if (mBootScriptSmst != NULL) {
- if (mRegistrationSmmExitBootServices != NULL) {
- //
- // Unregister SmmExitBootServices notification.
- //
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmExitBootServicesProtocolGuid,
- NULL,
- &mRegistrationSmmExitBootServices
- );
- ASSERT_EFI_ERROR (Status);
- }
- if (mRegistrationSmmLegacyBoot != NULL) {
- //
- // Unregister SmmLegacyBoot notification.
- //
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmLegacyBootProtocolGuid,
- NULL,
- &mRegistrationSmmLegacyBoot
- );
- ASSERT_EFI_ERROR (Status);
- }
- if (mRegistrationSmmReadyToLock != NULL) {
- //
- // Unregister SmmReadyToLock notification.
- //
- Status = mBootScriptSmst->SmmRegisterProtocolNotify (
- &gEfiSmmReadyToLockProtocolGuid,
- NULL,
- &mRegistrationSmmReadyToLock
- );
- ASSERT_EFI_ERROR (Status);
- }
- }
- //
- // Free the resources allocated and set PCDs to 0.
- //
- if (mS3BootScriptTableAllocated) {
- Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)mS3BootScriptTablePtr, EFI_SIZE_TO_PAGES (sizeof (SCRIPT_TABLE_PRIVATE_DATA)));
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet64S (PcdS3BootScriptTablePrivateDataPtr, 0);
- ASSERT_EFI_ERROR (Status);
- }
- if ((mBootScriptSmst != NULL) && mS3BootScriptTableSmmAllocated) {
- Status = mBootScriptSmst->SmmFreePool (mS3BootScriptTableSmmPtr);
- ASSERT_EFI_ERROR (Status);
- Status = PcdSet64S (PcdS3BootScriptTablePrivateSmmDataPtr, 0);
- ASSERT_EFI_ERROR (Status);
- }
- return RETURN_SUCCESS;
- }
- /**
- To get the start address from which a new boot time s3 boot script entry will write into.
- If the table is not exist, the functio will first allocate a buffer for the table
- If the table buffer is not enough for the new entry, in non-smm mode, the funtion will
- invoke reallocate to enlarge buffer.
- @param EntryLength the new entry length.
- @retval the address from which the a new s3 boot script entry will write into
- **/
- UINT8 *
- S3BootScriptGetBootTimeEntryAddAddress (
- UINT8 EntryLength
- )
- {
- EFI_PHYSICAL_ADDRESS S3TableBase;
- EFI_PHYSICAL_ADDRESS NewS3TableBase;
- UINT8 *NewEntryPtr;
- UINT32 TableLength;
- UINT16 PageNumber;
- EFI_STATUS Status;
- EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;
- S3TableBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(mS3BootScriptTablePtr->TableBase);
- if (S3TableBase == 0) {
- //
- // The table is not exist. This is the first to add entry.
- // Allocate ACPI script table space under 4G memory.
- //
- S3TableBase = 0xffffffff;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- 2 + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber),
- (EFI_PHYSICAL_ADDRESS *)&S3TableBase
- );
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return 0;
- }
- //
- // Fill Table Header
- //
- ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER *)(UINTN)S3TableBase;
- ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
- ScriptTableInfo->Length = (UINT8)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- ScriptTableInfo->Version = BOOT_SCRIPT_TABLE_VERSION;
- ScriptTableInfo->TableLength = 0; // will be calculate at CloseTable
- mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- mS3BootScriptTablePtr->TableBase = (UINT8 *)(UINTN)S3TableBase;
- mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16)(2 + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
- }
- // Here we do not count the reserved memory for runtime script table.
- PageNumber = (UINT16)(mS3BootScriptTablePtr->TableMemoryPageNumber - PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
- TableLength = mS3BootScriptTablePtr->TableLength;
- if (EFI_PAGES_TO_SIZE ((UINTN)PageNumber) < (TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE))) {
- //
- // The buffer is too small to hold the table, Reallocate the buffer
- //
- NewS3TableBase = 0xffffffff;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- 2 + PageNumber + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber),
- (EFI_PHYSICAL_ADDRESS *)&NewS3TableBase
- );
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- return 0;
- }
- CopyMem ((VOID *)(UINTN)NewS3TableBase, (VOID *)(UINTN)S3TableBase, TableLength);
- gBS->FreePages (S3TableBase, mS3BootScriptTablePtr->TableMemoryPageNumber);
- mS3BootScriptTablePtr->TableBase = (UINT8 *)(UINTN)NewS3TableBase;
- mS3BootScriptTablePtr->TableMemoryPageNumber = (UINT16)(2 + PageNumber + PcdGet16 (PcdS3BootScriptRuntimeTableReservePageNumber));
- }
- //
- // calculate the the start address for the new entry.
- //
- NewEntryPtr = mS3BootScriptTablePtr->TableBase + TableLength;
- //
- // update the table lenghth
- //
- mS3BootScriptTablePtr->TableLength = TableLength + EntryLength;
- //
- // In the boot time, we will not append the termination entry to the boot script
- // table until the callers think there is no boot time data that should be added and
- // it is caller's responsibility to explicit call the CloseTable.
- //
- //
- return NewEntryPtr;
- }
- /**
- To get the start address from which a new runtime(after SmmReadyToLock) s3 boot script entry will write into.
- In this case, it should be ensured that there is enough buffer to hold the entry.
- @param EntryLength the new entry length.
- @retval the address from which the a new s3 runtime(after SmmReadyToLock) script entry will write into
- **/
- UINT8 *
- S3BootScriptGetRuntimeEntryAddAddress (
- UINT8 EntryLength
- )
- {
- UINT8 *NewEntryPtr;
- NewEntryPtr = NULL;
- //
- // Check if the memory range reserved for S3 Boot Script table is large enough to hold the node.
- //
- if ((mS3BootScriptTablePtr->TableLength + EntryLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE)) <= EFI_PAGES_TO_SIZE ((UINTN)(mS3BootScriptTablePtr->TableMemoryPageNumber))) {
- NewEntryPtr = mS3BootScriptTablePtr->TableBase + mS3BootScriptTablePtr->TableLength;
- mS3BootScriptTablePtr->TableLength = mS3BootScriptTablePtr->TableLength + EntryLength;
- //
- // Append a terminate node on every insert
- //
- S3BootScriptInternalCloseTable ();
- }
- return (UINT8 *)NewEntryPtr;
- }
- /**
- This function is to restore boot time boot script data from LockBox.
- **/
- VOID
- RestoreBootTimeDataFromLockBox (
- VOID
- )
- {
- EFI_STATUS Status;
- UINTN LockBoxLength;
- //
- // Restore boot time boot script data from LockBox.
- //
- LockBoxLength = mS3BootScriptTablePtr->BootTimeScriptLength;
- Status = RestoreLockBox (
- &mBootScriptDataBootTimeGuid,
- (VOID *)mS3BootScriptTablePtr->TableBase,
- &LockBoxLength
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Update the data to BootScriptData LockBox.
- //
- Status = UpdateLockBox (
- &mBootScriptDataGuid,
- 0,
- (VOID *)mS3BootScriptTablePtr->TableBase,
- LockBoxLength
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Update TableLength.
- //
- mS3BootScriptTablePtr->TableLength = (UINT32)(mS3BootScriptTablePtr->BootTimeScriptLength - sizeof (EFI_BOOT_SCRIPT_TERMINATE));
- }
- /**
- To get the start address from which a new s3 boot script entry will write into.
- @param EntryLength the new entry length.
- @retval the address from which the a new s3 boot script entry will write into
- **/
- UINT8 *
- S3BootScriptGetEntryAddAddress (
- UINT8 EntryLength
- )
- {
- UINT8 *NewEntryPtr;
- if (!mS3BootScriptAcpiS3Enable) {
- return NULL;
- }
- if (mS3BootScriptTablePtr->SmmLocked) {
- //
- // We need check InSmm, because after SmmReadyToLock, only SMM driver is allowed to write boot script.
- //
- if (!mS3BootScriptTablePtr->InSmm) {
- //
- // Add DEBUG ERROR, so that we can find it after SmmReadyToLock.
- // Do not use ASSERT, because we may have test to invoke this interface.
- //
- DEBUG ((DEBUG_ERROR, "FATAL ERROR: Set boot script outside SMM after SmmReadyToLock!!!\n"));
- return NULL;
- }
- if (mS3BootScriptTablePtr->BackFromS3) {
- //
- // Back from S3, restore boot time boot script data from LockBox
- // and set BackFromS3 flag back to FALSE.
- //
- RestoreBootTimeDataFromLockBox ();
- mS3BootScriptTablePtr->BackFromS3 = FALSE;
- }
- NewEntryPtr = S3BootScriptGetRuntimeEntryAddAddress (EntryLength);
- } else {
- NewEntryPtr = S3BootScriptGetBootTimeEntryAddAddress (EntryLength);
- }
- return NewEntryPtr;
- }
- /**
- Sync BootScript LockBox data.
- @param Script The address from where the boot script has been added or updated.
- **/
- VOID
- SyncBootScript (
- IN UINT8 *Script
- )
- {
- EFI_STATUS Status;
- UINT32 ScriptOffset;
- UINT32 TotalScriptLength;
- if (!mS3BootScriptTablePtr->SmmLocked || !mS3BootScriptTablePtr->InSmm) {
- //
- // If it is not after SmmReadyToLock in SMM,
- // just return.
- //
- return;
- }
- ScriptOffset = (UINT32)(Script - mS3BootScriptTablePtr->TableBase);
- TotalScriptLength = (UINT32)(mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE));
- //
- // Update BootScriptData
- // So in S3 resume, the data can be restored correctly.
- //
- Status = UpdateLockBox (
- &mBootScriptDataGuid,
- ScriptOffset,
- (VOID *)((UINTN)mS3BootScriptTablePtr->TableBase + ScriptOffset),
- TotalScriptLength - ScriptOffset
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Now the length field is updated, need sync to lockbox.
- // So at S3 resume, the data can be restored correctly.
- //
- Status = UpdateLockBox (
- &mBootScriptDataGuid,
- OFFSET_OF (EFI_BOOT_SCRIPT_TABLE_HEADER, TableLength),
- &TotalScriptLength,
- sizeof (TotalScriptLength)
- );
- ASSERT_EFI_ERROR (Status);
- }
- /**
- This is an function to close the S3 boot script table. The function could only be called in
- BOOT time phase. To comply with the Framework spec definition on
- EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable(), this function will fulfill following things:
- 1. Closes the specified boot script table
- 2. It allocates a new memory pool to duplicate all the boot scripts in the specified table.
- Once this function is called, the table maintained by the library will be destroyed
- after it is copied into the allocated pool.
- 3. Any attempts to add a script record after calling this function will cause a new table
- to be created by the library.
- 4. The base address of the allocated pool will be returned in Address. Note that after
- using the boot script table, the CALLER is responsible for freeing the pool that is allocated
- by this function.
- In Spec PI1.1, this EFI_BOOT_SCRIPT_SAVE_PROTOCOL.CloseTable() is retired. To provides this API for now is
- for Framework Spec compatibility.
- If anyone does call CloseTable() on a real platform, then the caller is responsible for figuring out
- how to get the script to run at S3 resume because the boot script maintained by the lib will be
- destroyed.
- @return the base address of the new copy of the boot script table.
- @note this function could only called in boot time phase
- **/
- UINT8 *
- EFIAPI
- S3BootScriptCloseTable (
- VOID
- )
- {
- UINT8 *S3TableBase;
- UINT32 TableLength;
- UINT8 *Buffer;
- EFI_STATUS Status;
- EFI_BOOT_SCRIPT_TABLE_HEADER *ScriptTableInfo;
- S3TableBase = mS3BootScriptTablePtr->TableBase;
- if (S3TableBase == 0) {
- return 0;
- }
- //
- // Append the termination record the S3 boot script table
- //
- S3BootScriptInternalCloseTable ();
- TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
- //
- // Allocate the buffer and copy the boot script to the buffer.
- //
- Status = gBS->AllocatePool (
- EfiBootServicesData,
- (UINTN)TableLength,
- (VOID **)&Buffer
- );
- if (EFI_ERROR (Status)) {
- return 0;
- }
- CopyMem (Buffer, S3TableBase, TableLength);
- //
- // Destroy the table maintained by the library so that the next write operation
- // will write the record to the first entry of the table.
- //
- // Fill the table header.
- ScriptTableInfo = (EFI_BOOT_SCRIPT_TABLE_HEADER *)S3TableBase;
- ScriptTableInfo->OpCode = S3_BOOT_SCRIPT_LIB_TABLE_OPCODE;
- ScriptTableInfo->Length = (UINT8)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- ScriptTableInfo->TableLength = 0; // will be calculate at close the table
- mS3BootScriptTablePtr->TableLength = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- return Buffer;
- }
- /**
- Save I/O write to boot script
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The base address of the I/O operations.
- @param Count The number of I/O operations to perform.
- @param Buffer The source buffer from which to write data.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveIoWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_IO_WRITE ScriptIoWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- //
- // Truncation check
- //
- if ((Count > MAX_UINT8) ||
- (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_IO_WRITE)))
- {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // save script data
- //
- ScriptIoWrite.OpCode = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE;
- ScriptIoWrite.Length = Length;
- ScriptIoWrite.Width = Width;
- ScriptIoWrite.Address = Address;
- ScriptIoWrite.Count = (UINT32)Count;
- CopyMem ((VOID *)Script, (VOID *)&ScriptIoWrite, sizeof (EFI_BOOT_SCRIPT_IO_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for an I/O modify operation into a S3 boot script table
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The base address of the I/O operations.
- @param Data A pointer to the data to be OR-ed.
- @param DataMask A pointer to the data mask to be AND-ed with the data read from the register
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveIoReadWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_IO_READ_WRITE ScriptIoReadWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptIoReadWrite.OpCode = EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE;
- ScriptIoReadWrite.Length = Length;
- ScriptIoReadWrite.Width = Width;
- ScriptIoReadWrite.Address = Address;
- CopyMem ((VOID *)Script, (VOID *)&ScriptIoReadWrite, sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE)), Data, WidthInByte);
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a memory write operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The base address of the memory operations
- @param Count The number of memory operations to perform.
- @param Buffer The source buffer from which to write the data.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveMemWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_MEM_WRITE ScriptMemWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- //
- // Truncation check
- //
- if ((Count > MAX_UINT8) ||
- (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)))
- {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_WRITE) + (WidthInByte * Count));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptMemWrite.OpCode = EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE;
- ScriptMemWrite.Length = Length;
- ScriptMemWrite.Width = Width;
- ScriptMemWrite.Address = Address;
- ScriptMemWrite.Count = (UINT32)Count;
- CopyMem ((VOID *)Script, (VOID *)&ScriptMemWrite, sizeof (EFI_BOOT_SCRIPT_MEM_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a memory modify operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The base address of the memory operations. Address needs alignment if required
- @param Data A pointer to the data to be OR-ed.
- @param DataMask A pointer to the data mask to be AND-ed with the data read from the register.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveMemReadWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_MEM_READ_WRITE ScriptMemReadWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptMemReadWrite.OpCode = EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE;
- ScriptMemReadWrite.Length = Length;
- ScriptMemReadWrite.Width = Width;
- ScriptMemReadWrite.Address = Address;
- CopyMem ((VOID *)Script, (VOID *)&ScriptMemReadWrite, sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE)), Data, WidthInByte);
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a PCI configuration space write operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The address within the PCI configuration space.
- @param Count The number of PCI operations to perform.
- @param Buffer The source buffer from which to write the data.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePciCfgWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE ScriptPciWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- //
- // Truncation check
- //
- if ((Count > MAX_UINT8) ||
- (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)))
- {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPciWrite.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE;
- ScriptPciWrite.Length = Length;
- ScriptPciWrite.Width = Width;
- ScriptPciWrite.Address = Address;
- ScriptPciWrite.Count = (UINT32)Count;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPciWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a PCI configuration space modify operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Address The address within the PCI configuration space.
- @param Data A pointer to the data to be OR-ed.The size depends on Width.
- @param DataMask A pointer to the data mask to be AND-ed.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN__SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePciCfgReadWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE ScriptPciReadWrite;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPciReadWrite.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE;
- ScriptPciReadWrite.Length = Length;
- ScriptPciReadWrite.Width = Width;
- ScriptPciReadWrite.Address = Address;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPciReadWrite, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE)), Data, WidthInByte);
- CopyMem (
- (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE) + WidthInByte),
- DataMask,
- WidthInByte
- );
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a PCI configuration 2 space write operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Segment The PCI segment number for Address.
- @param Address The address within the PCI configuration space.
- @param Count The number of PCI operations to perform.
- @param Buffer The source buffer from which to write the data.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePciCfg2Write (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT16 Segment,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE ScriptPciWrite2;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- //
- // Truncation check
- //
- if ((Count > MAX_UINT8) ||
- (WidthInByte * Count > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)))
- {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE) + (WidthInByte * Count));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPciWrite2.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE;
- ScriptPciWrite2.Length = Length;
- ScriptPciWrite2.Width = Width;
- ScriptPciWrite2.Address = Address;
- ScriptPciWrite2.Segment = Segment;
- ScriptPciWrite2.Count = (UINT32)Count;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPciWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE)), Buffer, WidthInByte * Count);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for a PCI configuration 2 space modify operation into a specified boot script table.
- @param Width The width of the I/O operations.Enumerated in S3_BOOT_SCRIPT_LIB_WIDTH.
- @param Segment The PCI segment number for Address.
- @param Address The address within the PCI configuration space.
- @param Data A pointer to the data to be OR-ed. The size depends on Width.
- @param DataMask A pointer to the data mask to be AND-ed.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePciCfg2ReadWrite (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT16 Segment,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE ScriptPciReadWrite2;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPciReadWrite2.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE;
- ScriptPciReadWrite2.Length = Length;
- ScriptPciReadWrite2.Width = Width;
- ScriptPciReadWrite2.Segment = Segment;
- ScriptPciReadWrite2.Address = Address;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPciReadWrite2, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE)), Data, WidthInByte);
- CopyMem (
- (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE) + WidthInByte),
- DataMask,
- WidthInByte
- );
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Checks the parameter of S3BootScriptSaveSmbusExecute().
- This function checks the input parameters of SmbusExecute(). If the input parameters are valid
- for certain SMBus bus protocol, it will return EFI_SUCCESS; otherwise, it will return certain
- error code based on the input SMBus bus protocol.
- @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
- and PEC.
- @param Operation Signifies which particular SMBus hardware protocol instance that
- it will use to execute the SMBus transactions. This SMBus
- hardware protocol is defined by the SMBus Specification and is
- not related to EFI.
- @param Length Signifies the number of bytes that this operation will do. The
- maximum number of bytes can be revision specific and operation
- specific. This field will contain the actual number of bytes that
- are executed for this operation. Not all operations require this
- argument.
- @param Buffer Contains the value of data to execute to the SMBus slave device.
- Not all operations require this argument. The length of this
- buffer is identified by Length.
- @retval EFI_SUCCESS All the parameters are valid for the corresponding SMBus bus
- protocol.
- @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION.
- @retval EFI_INVALID_PARAMETER Length/Buffer is NULL for operations except for EfiSmbusQuickRead
- and EfiSmbusQuickWrite. Length is outside the range of valid
- values.
- @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported.
- @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation.
- **/
- EFI_STATUS
- CheckParameters (
- IN UINTN SmBusAddress,
- IN EFI_SMBUS_OPERATION Operation,
- IN OUT UINTN *Length,
- IN VOID *Buffer
- )
- {
- EFI_STATUS Status;
- UINTN RequiredLen;
- EFI_SMBUS_DEVICE_COMMAND Command;
- BOOLEAN PecCheck;
- Command = SMBUS_LIB_COMMAND (SmBusAddress);
- PecCheck = SMBUS_LIB_PEC (SmBusAddress);
- //
- // Set default value to be 2:
- // for SmbusReadWord, SmbusWriteWord and SmbusProcessCall.
- //
- RequiredLen = 2;
- Status = EFI_SUCCESS;
- switch (Operation) {
- case EfiSmbusQuickRead:
- case EfiSmbusQuickWrite:
- if (PecCheck || (Command != 0)) {
- return EFI_UNSUPPORTED;
- }
- break;
- case EfiSmbusReceiveByte:
- case EfiSmbusSendByte:
- if (Command != 0) {
- return EFI_UNSUPPORTED;
- }
- //
- // Cascade to check length parameter.
- //
- case EfiSmbusReadByte:
- case EfiSmbusWriteByte:
- RequiredLen = 1;
- //
- // Cascade to check length parameter.
- //
- case EfiSmbusReadWord:
- case EfiSmbusWriteWord:
- case EfiSmbusProcessCall:
- if ((Buffer == NULL) || (Length == NULL)) {
- return EFI_INVALID_PARAMETER;
- } else if (*Length < RequiredLen) {
- Status = EFI_BUFFER_TOO_SMALL;
- }
- *Length = RequiredLen;
- break;
- case EfiSmbusReadBlock:
- case EfiSmbusWriteBlock:
- case EfiSmbusBWBRProcessCall:
- if ((Buffer == NULL) ||
- (Length == NULL) ||
- (*Length < MIN_SMBUS_BLOCK_LEN) ||
- (*Length > MAX_SMBUS_BLOCK_LEN))
- {
- return EFI_INVALID_PARAMETER;
- }
- break;
- default:
- return EFI_INVALID_PARAMETER;
- }
- return Status;
- }
- /**
- Adds a record for an SMBus command execution into a specified boot script table.
- @param SmBusAddress Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length, and PEC.
- @param Operation Indicates which particular SMBus protocol it will use to execute the SMBus
- transactions.
- @param Length A pointer to signify the number of bytes that this operation will do.
- @param Buffer Contains the value of data to execute to the SMBUS slave device.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveSmbusExecute (
- IN UINTN SmBusAddress,
- IN EFI_SMBUS_OPERATION Operation,
- IN UINTN *Length,
- IN VOID *Buffer
- )
- {
- EFI_STATUS Status;
- UINTN BufferLength;
- UINT8 DataSize;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_SMBUS_EXECUTE ScriptSmbusExecute;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if (Length == NULL) {
- BufferLength = 0;
- } else {
- BufferLength = *Length;
- }
- Status = CheckParameters (SmBusAddress, Operation, &BufferLength, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Truncation check
- //
- if (BufferLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)) {
- return RETURN_OUT_OF_RESOURCES;
- }
- DataSize = (UINT8)(sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE) + BufferLength);
- Script = S3BootScriptGetEntryAddAddress (DataSize);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptSmbusExecute.OpCode = EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE;
- ScriptSmbusExecute.Length = DataSize;
- ScriptSmbusExecute.SmBusAddress = (UINT64)SmBusAddress;
- ScriptSmbusExecute.Operation = Operation;
- ScriptSmbusExecute.DataSize = (UINT32)BufferLength;
- CopyMem ((VOID *)Script, (VOID *)&ScriptSmbusExecute, sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE));
- CopyMem (
- (VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)),
- Buffer,
- BufferLength
- );
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for an execution stall on the processor into a specified boot script table.
- @param Duration Duration in microseconds of the stall
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveStall (
- IN UINTN Duration
- )
- {
- UINT8 Length;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_STALL ScriptStall;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_STALL));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptStall.OpCode = EFI_BOOT_SCRIPT_STALL_OPCODE;
- ScriptStall.Length = Length;
- ScriptStall.Duration = Duration;
- CopyMem ((VOID *)Script, (VOID *)&ScriptStall, sizeof (EFI_BOOT_SCRIPT_STALL));
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for dispatching specified arbitrary code into a specified boot script table.
- @param EntryPoint Entry point of the code to be dispatched.
- @param Context Argument to be passed into the EntryPoint of the code to be dispatched.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveDispatch2 (
- IN VOID *EntryPoint,
- IN VOID *Context
- )
- {
- UINT8 Length;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_DISPATCH_2 ScriptDispatch2;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptDispatch2.OpCode = EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE;
- ScriptDispatch2.Length = Length;
- ScriptDispatch2.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
- ScriptDispatch2.Context = (EFI_PHYSICAL_ADDRESS)(UINTN)Context;
- CopyMem ((VOID *)Script, (VOID *)&ScriptDispatch2, sizeof (EFI_BOOT_SCRIPT_DISPATCH_2));
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for memory reads of the memory location and continues when the exit criteria is
- satisfied or after a defined duration.
- Please aware, below interface is different with PI specification, Vol 5:
- EFI_S3_SAVE_STATE_PROTOCOL.Write() for EFI_BOOT_SCRIPT_MEM_POLL_OPCODE.
- "Duration" below is microseconds, while "Delay" in PI specification means
- the number of 100ns units to poll.
- @param Width The width of the memory operations.
- @param Address The base address of the memory operations.
- @param BitMask A pointer to the bit mask to be AND-ed with the data read from the register.
- @param BitValue A pointer to the data value after to be Masked.
- @param Duration Duration in microseconds of the stall.
- @param LoopTimes The times of the register polling.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveMemPoll (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *BitMask,
- IN VOID *BitValue,
- IN UINTN Duration,
- IN UINT64 LoopTimes
- )
- {
- UINT8 Length;
- UINT8 *Script;
- UINT8 WidthInByte;
- EFI_BOOT_SCRIPT_MEM_POLL ScriptMemPoll;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptMemPoll.OpCode = EFI_BOOT_SCRIPT_MEM_POLL_OPCODE;
- ScriptMemPoll.Length = Length;
- ScriptMemPoll.Width = Width;
- ScriptMemPoll.Address = Address;
- ScriptMemPoll.Duration = Duration;
- ScriptMemPoll.LoopTimes = LoopTimes;
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL)), BitValue, WidthInByte);
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_MEM_POLL) + WidthInByte), BitMask, WidthInByte);
- CopyMem ((VOID *)Script, (VOID *)&ScriptMemPoll, sizeof (EFI_BOOT_SCRIPT_MEM_POLL));
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Store arbitrary information in the boot script table. This opcode is a no-op on dispatch and is only
- used for debugging script issues.
- @param InformationLength Length of the data in bytes
- @param Information Information to be logged in the boot scrpit
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveInformation (
- IN UINT32 InformationLength,
- IN VOID *Information
- )
- {
- UINT8 Length;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- //
- // Truncation check
- //
- if (InformationLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_INFORMATION)) {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptInformation.OpCode = EFI_BOOT_SCRIPT_INFORMATION_OPCODE;
- ScriptInformation.Length = Length;
- ScriptInformation.InformationLength = InformationLength;
- CopyMem ((VOID *)Script, (VOID *)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *)Information, (UINTN)InformationLength);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Store a string in the boot script table. This opcode is a no-op on dispatch and is only
- used for debugging script issues.
- @param String The string to save to boot script table
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveInformationAsciiString (
- IN CONST CHAR8 *String
- )
- {
- return S3BootScriptSaveInformation (
- (UINT32)AsciiStrLen (String) + 1,
- (VOID *)String
- );
- }
- /**
- Adds a record for dispatching specified arbitrary code into a specified boot script table.
- @param EntryPoint Entry point of the code to be dispatched.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveDispatch (
- IN VOID *EntryPoint
- )
- {
- UINT8 Length;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_DISPATCH ScriptDispatch;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_DISPATCH));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptDispatch.OpCode = EFI_BOOT_SCRIPT_DISPATCH_OPCODE;
- ScriptDispatch.Length = Length;
- ScriptDispatch.EntryPoint = (EFI_PHYSICAL_ADDRESS)(UINTN)EntryPoint;
- CopyMem ((VOID *)Script, (VOID *)&ScriptDispatch, sizeof (EFI_BOOT_SCRIPT_DISPATCH));
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for I/O reads the I/O location and continues when the exit criteria is satisfied or after a
- defined duration.
- @param Width The width of the I/O operations.
- @param Address The base address of the I/O operations.
- @param Data The comparison value used for the polling exit criteria.
- @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
- in Data are ignored when polling the memory address.
- @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
- granularity so the delay may be longer.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSaveIoPoll (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask,
- IN UINT64 Delay
- )
- {
- UINT8 WidthInByte;
- UINT8 *Script;
- UINT8 Length;
- EFI_BOOT_SCRIPT_IO_POLL ScriptIoPoll;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptIoPoll.OpCode = EFI_BOOT_SCRIPT_IO_POLL_OPCODE;
- ScriptIoPoll.Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_IO_POLL) + (WidthInByte * 2));
- ScriptIoPoll.Width = Width;
- ScriptIoPoll.Address = Address;
- ScriptIoPoll.Delay = Delay;
- CopyMem ((VOID *)Script, (VOID *)&ScriptIoPoll, sizeof (EFI_BOOT_SCRIPT_IO_POLL));
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL)), Data, WidthInByte);
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_IO_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
- after a defined duration.
- @param Width The width of the I/O operations.
- @param Address The address within the PCI configuration space.
- @param Data The comparison value used for the polling exit criteria.
- @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
- in Data are ignored when polling the memory address
- @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
- granularity so the delay may be longer.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePciPoll (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask,
- IN UINT64 Delay
- )
- {
- UINT8 *Script;
- UINT8 WidthInByte;
- UINT8 Length;
- EFI_BOOT_SCRIPT_PCI_CONFIG_POLL ScriptPciPoll;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPciPoll.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE;
- ScriptPciPoll.Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + (WidthInByte * 2));
- ScriptPciPoll.Width = Width;
- ScriptPciPoll.Address = Address;
- ScriptPciPoll.Delay = Delay;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPciPoll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL)), Data, WidthInByte);
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Adds a record for PCI configuration space reads and continues when the exit criteria is satisfied or
- after a defined duration.
- @param Width The width of the I/O operations.
- @param Segment The PCI segment number for Address.
- @param Address The address within the PCI configuration space.
- @param Data The comparison value used for the polling exit criteria.
- @param DataMask Mask used for the polling criteria. The bits in the bytes below Width which are zero
- in Data are ignored when polling the memory address
- @param Delay The number of 100ns units to poll. Note that timer available may be of poorer
- granularity so the delay may be longer.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- @note A known Limitations in the implementation which is 64bits operations are not supported.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptSavePci2Poll (
- IN S3_BOOT_SCRIPT_LIB_WIDTH Width,
- IN UINT16 Segment,
- IN UINT64 Address,
- IN VOID *Data,
- IN VOID *DataMask,
- IN UINT64 Delay
- )
- {
- UINT8 WidthInByte;
- UINT8 *Script;
- UINT8 Length;
- EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL ScriptPci2Poll;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if ((Width == S3BootScriptWidthUint64) ||
- (Width == S3BootScriptWidthFifoUint64) ||
- (Width == S3BootScriptWidthFillUint64))
- {
- return EFI_INVALID_PARAMETER;
- }
- WidthInByte = (UINT8)(0x01 << (Width & 0x03));
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptPci2Poll.OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE;
- ScriptPci2Poll.Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + (WidthInByte * 2));
- ScriptPci2Poll.Width = Width;
- ScriptPci2Poll.Segment = Segment;
- ScriptPci2Poll.Address = Address;
- ScriptPci2Poll.Delay = Delay;
- CopyMem ((VOID *)Script, (VOID *)&ScriptPci2Poll, sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL)), Data, WidthInByte);
- CopyMem ((UINT8 *)(Script + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL) + WidthInByte), DataMask, WidthInByte);
- SyncBootScript (Script);
- return RETURN_SUCCESS;
- }
- /**
- Do the calculation of start address from which a new s3 boot script entry will write into.
- @param EntryLength The new entry length.
- @param Position specifies the position in the boot script table where the opcode will be
- inserted, either before or after, depending on BeforeOrAfter.
- @param BeforeOrAfter The flag to indicate to insert the nod before or after the position.
- This parameter is effective when InsertFlag is TRUE
- @param Script return out the position from which the a new s3 boot script entry will write into
- **/
- VOID
- S3BootScriptCalculateInsertAddress (
- IN UINT8 EntryLength,
- IN VOID *Position OPTIONAL,
- IN BOOLEAN BeforeOrAfter OPTIONAL,
- OUT UINT8 **Script
- )
- {
- UINTN TableLength;
- UINT8 *S3TableBase;
- UINTN PositionOffset;
- EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
- //
- // The entry inserting to table is already added to the end of the table
- //
- TableLength = mS3BootScriptTablePtr->TableLength - EntryLength;
- S3TableBase = mS3BootScriptTablePtr->TableBase;
- //
- // calculate the Position offset
- //
- if (Position != NULL) {
- PositionOffset = (UINTN)Position - (UINTN)S3TableBase;
- //
- // If the BeforeOrAfter is FALSE, that means to insert the node right after the node.
- //
- if (!BeforeOrAfter) {
- CopyMem ((VOID *)&ScriptHeader, Position, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
- PositionOffset += (ScriptHeader.Length);
- }
- //
- // Insert the node before the adjusted Position
- //
- CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);
- //
- // calculate the the start address for the new entry.
- //
- *Script = S3TableBase + PositionOffset;
- } else {
- if (!BeforeOrAfter) {
- //
- // Insert the node to the end of the table
- //
- *Script = S3TableBase + TableLength;
- } else {
- //
- // Insert the node to the beginning of the table
- //
- PositionOffset = (UINTN)sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- CopyMem (S3TableBase+PositionOffset+EntryLength, S3TableBase+PositionOffset, TableLength - PositionOffset);
- *Script = S3TableBase + PositionOffset;
- }
- }
- }
- /**
- Move the last boot script entry to the position
- @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
- in the boot script table specified by Position. If Position is NULL or points to
- NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
- of the table (if FALSE).
- @param Position On entry, specifies the position in the boot script table where the opcode will be
- inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
- the position of the inserted opcode in the boot script table.
- @retval RETURN_OUT_OF_RESOURCES The table is not available.
- @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
- @retval RETURN_SUCCESS Opcode is inserted no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptMoveLastOpcode (
- IN BOOLEAN BeforeOrAfter,
- IN OUT VOID **Position OPTIONAL
- )
- {
- UINT8 *Script;
- VOID *TempPosition;
- UINTN StartAddress;
- UINT32 TableLength;
- EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
- BOOLEAN ValidatePosition;
- UINT8 *LastOpcode;
- UINT8 TempBootScriptEntry[BOOT_SCRIPT_NODE_MAX_LENGTH];
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- ValidatePosition = FALSE;
- TempPosition = (Position == NULL) ? NULL : (*Position);
- //
- // Check that the script is initialized and synced without adding an entry to the script.
- //
- Script = S3BootScriptGetEntryAddAddress (0);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- Script = mS3BootScriptTablePtr->TableBase;
- StartAddress = (UINTN)Script;
- TableLength = mS3BootScriptTablePtr->TableLength;
- Script = Script + sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER);
- LastOpcode = Script;
- //
- // Find the last boot Script Entry which is not the terminate node
- //
- while ((UINTN)Script < (UINTN)(StartAddress + TableLength)) {
- CopyMem ((VOID *)&ScriptHeader, Script, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
- if ((TempPosition != NULL) && (TempPosition == Script)) {
- //
- // If the position is specified, the position must be pointed to a boot script entry start address.
- //
- ValidatePosition = TRUE;
- }
- if (ScriptHeader.OpCode != S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE) {
- LastOpcode = Script;
- }
- Script = Script + ScriptHeader.Length;
- }
- //
- // If the position is specified, but not the start of a boot script entry, it is a invalid input
- //
- if ((TempPosition != NULL) && !ValidatePosition) {
- return RETURN_INVALID_PARAMETER;
- }
- CopyMem ((VOID *)&ScriptHeader, LastOpcode, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
- CopyMem ((VOID *)TempBootScriptEntry, LastOpcode, ScriptHeader.Length);
- //
- // Find the right position to write the node in
- //
- S3BootScriptCalculateInsertAddress (
- ScriptHeader.Length,
- TempPosition,
- BeforeOrAfter,
- &Script
- );
- //
- // Copy the node to Boot script table
- //
- CopyMem ((VOID *)Script, (VOID *)TempBootScriptEntry, ScriptHeader.Length);
- SyncBootScript (Script);
- //
- // return out the Position
- //
- if (Position != NULL) {
- *Position = Script;
- }
- return RETURN_SUCCESS;
- }
- /**
- Create a Label node in the boot script table.
- @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE) or after (FALSE) the position
- in the boot script table specified by Position. If Position is NULL or points to
- NULL then the new opcode is inserted at the beginning of the table (if TRUE) or end
- of the table (if FALSE).
- @param Position On entry, specifies the position in the boot script table where the opcode will be
- inserted, either before or after, depending on BeforeOrAfter. On exit, specifies
- the position of the inserted opcode in the boot script table.
- @param InformationLength Length of the label in bytes
- @param Information Label to be logged in the boot scrpit
- @retval RETURN_INVALID_PARAMETER The Position is not a valid position in the boot script table.
- @retval RETURN_OUT_OF_RESOURCES Not enough memory for the table do operation.
- @retval RETURN_SUCCESS Opcode is added or no action is required as ACPI S3 was disabled.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptLabelInternal (
- IN BOOLEAN BeforeOrAfter,
- IN OUT VOID **Position OPTIONAL,
- IN UINT32 InformationLength,
- IN CONST CHAR8 *Information
- )
- {
- UINT8 Length;
- UINT8 *Script;
- EFI_BOOT_SCRIPT_INFORMATION ScriptInformation;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- //
- // Truncation check
- //
- if (InformationLength > MAX_UINT8 - sizeof (EFI_BOOT_SCRIPT_INFORMATION)) {
- return RETURN_OUT_OF_RESOURCES;
- }
- Length = (UINT8)(sizeof (EFI_BOOT_SCRIPT_INFORMATION) + InformationLength);
- Script = S3BootScriptGetEntryAddAddress (Length);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Build script data
- //
- ScriptInformation.OpCode = S3_BOOT_SCRIPT_LIB_LABEL_OPCODE;
- ScriptInformation.Length = Length;
- ScriptInformation.InformationLength = InformationLength;
- CopyMem ((VOID *)Script, (VOID *)&ScriptInformation, sizeof (EFI_BOOT_SCRIPT_INFORMATION));
- CopyMem ((VOID *)(Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION)), (VOID *)Information, (UINTN)InformationLength);
- SyncBootScript (Script);
- return S3BootScriptMoveLastOpcode (BeforeOrAfter, Position);
- }
- /**
- Find a label within the boot script table and, if not present, optionally create it.
- @param BeforeOrAfter Specifies whether the opcode is stored before (TRUE)
- or after (FALSE) the position in the boot script table
- specified by Position.
- @param CreateIfNotFound Specifies whether the label will be created if the label
- does not exists (TRUE) or not (FALSE).
- @param Position On entry, specifies the position in the boot script table
- where the opcode will be inserted, either before or after,
- depending on BeforeOrAfter. On exit, specifies the position
- of the inserted opcode in the boot script table.
- @param Label Points to the label which will be inserted in the boot script table.
- @retval EFI_SUCCESS The operation succeeded or no action is required.
- A record was added into the specified script table if ACPI S3 was enabled.
- @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
- If the opcode is unknow or not supported because of the PCD
- Feature Flags.
- @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptLabel (
- IN BOOLEAN BeforeOrAfter,
- IN BOOLEAN CreateIfNotFound,
- IN OUT VOID **Position OPTIONAL,
- IN CONST CHAR8 *Label
- )
- {
- UINT8 *Script;
- UINTN StartAddress;
- UINT32 TableLength;
- EFI_BOOT_SCRIPT_COMMON_HEADER ScriptHeader;
- EFI_BOOT_SCRIPT_TABLE_HEADER TableHeader;
- UINT32 LabelLength;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- //
- // Check NULL Label
- //
- if (Label == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check empty Label
- //
- if (Label[0] == '\0') {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check that the script is initialized and synced without adding an entry to the script.
- // The code must search for the label first before it knows if a new entry needs
- // to be added.
- //
- Script = S3BootScriptGetEntryAddAddress (0);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- //
- // Check the header and search for existing label.
- //
- Script = mS3BootScriptTablePtr->TableBase;
- CopyMem ((VOID *)&TableHeader, Script, sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER));
- if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
- return EFI_INVALID_PARAMETER;
- }
- StartAddress = (UINTN)Script;
- TableLength = mS3BootScriptTablePtr->TableLength;
- Script = Script + TableHeader.Length;
- while ((UINTN)Script < (UINTN)(StartAddress + TableLength)) {
- CopyMem ((VOID *)&ScriptHeader, Script, sizeof (EFI_BOOT_SCRIPT_COMMON_HEADER));
- if (ScriptHeader.OpCode == S3_BOOT_SCRIPT_LIB_LABEL_OPCODE) {
- if (AsciiStrCmp ((CHAR8 *)(UINTN)(Script+sizeof (EFI_BOOT_SCRIPT_INFORMATION)), Label) == 0) {
- (*Position) = Script;
- return EFI_SUCCESS;
- }
- }
- Script = Script + ScriptHeader.Length;
- }
- if (CreateIfNotFound) {
- LabelLength = (UINT32)AsciiStrSize (Label);
- return S3BootScriptLabelInternal (BeforeOrAfter, Position, LabelLength, Label);
- } else {
- return EFI_NOT_FOUND;
- }
- }
- /**
- Compare two positions in the boot script table and return their relative position.
- @param Position1 The positions in the boot script table to compare
- @param Position2 The positions in the boot script table to compare
- @param RelativePosition On return, points to the result of the comparison
- @retval EFI_SUCCESS The operation succeeded or no action is required.
- A record was added into the specified script table if ACPI S3 was enabled.
- @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported.
- If the opcode is unknow or not supported because of the PCD
- Feature Flags.
- @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script.
- **/
- RETURN_STATUS
- EFIAPI
- S3BootScriptCompare (
- IN UINT8 *Position1,
- IN UINT8 *Position2,
- OUT UINTN *RelativePosition
- )
- {
- UINT8 *Script;
- UINT32 TableLength;
- if (!mS3BootScriptAcpiS3Enable) {
- return RETURN_SUCCESS;
- }
- if (RelativePosition == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check that the script is initialized and synced without adding an entry to the script.
- //
- Script = S3BootScriptGetEntryAddAddress (0);
- if (Script == NULL) {
- return RETURN_OUT_OF_RESOURCES;
- }
- Script = mS3BootScriptTablePtr->TableBase;
- //
- // mS3BootScriptTablePtr->TableLength does not include the termination node, so add it up
- //
- TableLength = mS3BootScriptTablePtr->TableLength + sizeof (EFI_BOOT_SCRIPT_TERMINATE);
- if ((Position1 < Script) || (Position1 > Script+TableLength)) {
- return EFI_INVALID_PARAMETER;
- }
- if ((Position2 < Script) || (Position2 > Script+TableLength)) {
- return EFI_INVALID_PARAMETER;
- }
- *RelativePosition = (Position1 < Position2) ? -1 : ((Position1 == Position2) ? 0 : 1);
- return EFI_SUCCESS;
- }
|