diff --git a/stand/efi/Makefile b/stand/efi/Makefile index 1887b9536a5b5f..6147d2d7734bcb 100644 --- a/stand/efi/Makefile +++ b/stand/efi/Makefile @@ -5,6 +5,8 @@ NO_OBJ=t SUBDIR.yes+= libefi SUBDIR.${MK_LOADER_IA32}+= libefi32 SUBDIR.${MK_FDT}+= fdt +SUBDIR.yes+= libacpi +SUBDIR.${MK_LOADER_IA32}+= libacpi32 SUBDIR.yes+= .WAIT SUBDIR.yes+= boot1 gptboot diff --git a/stand/efi/contrib/dev/acpica/os_specific/service_layers/osunixxf.c b/stand/efi/contrib/dev/acpica/os_specific/service_layers/osunixxf.c new file mode 100644 index 00000000000000..ec32a29064ff26 --- /dev/null +++ b/stand/efi/contrib/dev/acpica/os_specific/service_layers/osunixxf.c @@ -0,0 +1,1526 @@ +/****************************************************************************** + * + * Module Name: osunixxf - UNIX OSL interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include +#include + +/* + * These interfaces are required in order to compile the ASL compiler and the + * various ACPICA tools under Linux or other Unix-like system. + */ +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_OS_SERVICES + ACPI_MODULE_NAME ("osunixxf") + +/* Upcalls to AcpiExec */ + +void +AeTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); + +typedef void* (*PTHREAD_CALLBACK) (void *); + +/* Buffer used by AcpiOsVprintf */ + +#define ACPI_VPRINTF_BUFFER_SIZE 512 +#define _ASCII_NEWLINE '\n' + +/* Terminal support for AcpiExec only */ + +#ifdef ACPI_EXEC_APP +#include + +struct termios OriginalTermAttributes; +int TermAttributesWereSet = 0; + +ACPI_STATUS +AcpiUtReadLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead); + +static void +OsEnterLineEditMode ( + void); + +static void +OsExitLineEditMode ( + void); + + +/****************************************************************************** + * + * FUNCTION: OsEnterLineEditMode, OsExitLineEditMode + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Enter/Exit the raw character input mode for the terminal. + * + * Interactive line-editing support for the AML debugger. Used with the + * common/acgetline module. + * + * readline() is not used because of non-portability. It is not available + * on all systems, and if it is, often the package must be manually installed. + * + * Therefore, we use the POSIX tcgetattr/tcsetattr and do the minimal line + * editing that we need in AcpiOsGetLine. + * + * If the POSIX tcgetattr/tcsetattr interfaces are unavailable, these + * calls will also work: + * For OsEnterLineEditMode: system ("stty cbreak -echo") + * For OsExitLineEditMode: system ("stty cooked echo") + * + *****************************************************************************/ + +static void +OsEnterLineEditMode ( + void) +{ + struct termios LocalTermAttributes; + + + TermAttributesWereSet = 0; + + /* STDIN must be a terminal */ + + if (!isatty (STDIN_FILENO)) + { + return; + } + + /* Get and keep the original attributes */ + + if (tcgetattr (STDIN_FILENO, &OriginalTermAttributes)) + { + fprintf (stderr, "Could not get terminal attributes!\n"); + return; + } + + /* Set the new attributes to enable raw character input */ + + memcpy (&LocalTermAttributes, &OriginalTermAttributes, + sizeof (struct termios)); + + LocalTermAttributes.c_lflag &= ~(ICANON | ECHO); + LocalTermAttributes.c_cc[VMIN] = 1; + LocalTermAttributes.c_cc[VTIME] = 0; + + if (tcsetattr (STDIN_FILENO, TCSANOW, &LocalTermAttributes)) + { + fprintf (stderr, "Could not set terminal attributes!\n"); + return; + } + + TermAttributesWereSet = 1; +} + + +static void +OsExitLineEditMode ( + void) +{ + + if (!TermAttributesWereSet) + { + return; + } + + /* Set terminal attributes back to the original values */ + + if (tcsetattr (STDIN_FILENO, TCSANOW, &OriginalTermAttributes)) + { + fprintf (stderr, "Could not restore terminal attributes!\n"); + } +} + + +#else + +/* These functions are not needed for other ACPICA utilities */ + +#define OsEnterLineEditMode() +#define OsExitLineEditMode() +#endif + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInitialize, AcpiOsTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize and terminate this module. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsInitialize ( + void) +{ + OsEnterLineEditMode (); + + return (AE_OK); +} + +ACPI_STATUS +AcpiOsTerminate ( + void) +{ + + OsExitLineEditMode (); + return (AE_OK); +} + + +#ifndef ACPI_USE_NATIVE_RSDP_POINTER +/****************************************************************************** + * + * FUNCTION: AcpiOsGetRootPointer + * + * PARAMETERS: None + * + * RETURN: RSDP physical address + * + * DESCRIPTION: Gets the ACPI root pointer (RSDP) + * + *****************************************************************************/ + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void) +{ + + return (0); +} +#endif + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPredefinedOverride + * + * PARAMETERS: InitVal - Initial value of the predefined object + * NewVal - The new value for the object + * + * RETURN: Status, pointer to value. Null pointer returned if not + * overriding. + * + * DESCRIPTION: Allow the OS to override predefined names + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal) +{ + + if (!InitVal || !NewVal) + { + return (AE_BAD_PARAMETER); + } + + *NewVal = NULL; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably + * firmware) + * NewTable - Where an entire new table is returned. + * + * RETURN: Status, pointer to new table. Null pointer returned if no + * table is available to override + * + * DESCRIPTION: Return a different version of a table if one is available + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable) +{ + + if (!ExistingTable || !NewTable) + { + return (AE_BAD_PARAMETER); + } + + *NewTable = NULL; + +#ifdef ACPI_EXEC_APP + + AeTableOverride (ExistingTable, NewTable); + return (AE_OK); +#else + + return (AE_NO_ACPI_TABLES); +#endif +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPhysicalTableOverride + * + * PARAMETERS: ExistingTable - Header of current table (probably firmware) + * NewAddress - Where new table address is returned + * (Physical address) + * NewTableLength - Where new table length is returned + * + * RETURN: Status, address/length of new table. Null pointer returned + * if no table is available to override. + * + * DESCRIPTION: Returns AE_SUPPORT, function not used in user space. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength) +{ + + return (AE_SUPPORT); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsEnterSleep + * + * PARAMETERS: SleepState - Which sleep state to enter + * RegaValue - Register A value + * RegbValue - Register B value + * + * RETURN: Status + * + * DESCRIPTION: A hook before writing sleep registers to enter the sleep + * state. Return AE_CTRL_TERMINATE to skip further sleep register + * writes. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsEnterSleep ( + UINT8 SleepState, + UINT32 RegaValue, + UINT32 RegbValue) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsPrintf + * + * PARAMETERS: fmt, ... - Standard printf format + * + * RETURN: None + * + * DESCRIPTION: Formatted output. Note: very similar to AcpiOsVprintf + * (performance), changes should be tracked in both functions. + * + *****************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiOsPrintf ( + const char *Fmt, + ...) +{ + /* No-op */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsVprintf + * + * PARAMETERS: fmt - Standard printf format + * args - Argument list + * + * RETURN: None + * + * DESCRIPTION: Formatted output with argument list pointer. Note: very + * similar to AcpiOsPrintf, changes should be tracked in both + * functions. + * + *****************************************************************************/ + +void +AcpiOsVprintf ( + const char *Fmt, + va_list Args) +{ + /* No-op */ +} + + +#ifndef ACPI_EXEC_APP +/****************************************************************************** + * + * FUNCTION: AcpiOsGetLine + * + * PARAMETERS: Buffer - Where to return the command line + * BufferLength - Maximum length of Buffer + * BytesRead - Where the actual byte count is returned + * + * RETURN: Status and actual bytes read + * + * DESCRIPTION: Get the next input line from the terminal. NOTE: For the + * AcpiExec utility, we use the acgetline module instead to + * provide line-editing and history support. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsGetLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead) +{ + int InputChar; + UINT32 EndOfLine; + + + /* Standard AcpiOsGetLine for all utilities except AcpiExec */ + + for (EndOfLine = 0; ; EndOfLine++) + { + if (EndOfLine >= BufferLength) + { + return (AE_BUFFER_OVERFLOW); + } + + /* EOF DNE - XXX + if ((InputChar = getchar ()) == EOF) + { + return (AE_ERROR); + } + */ + + if (!InputChar || InputChar == _ASCII_NEWLINE) + { + break; + } + + Buffer[EndOfLine] = (char) InputChar; + } + + /* Null terminate the buffer */ + + Buffer[EndOfLine] = 0; + + /* Return the number of bytes in the string */ + + if (BytesRead) + { + *BytesRead = EndOfLine; + } + + return (AE_OK); +} +#endif + + +#ifndef ACPI_USE_NATIVE_MEMORY_MAPPING +/****************************************************************************** + * + * FUNCTION: AcpiOsMapMemory + * + * PARAMETERS: where - Physical address of memory to be mapped + * length - How much memory to map + * + * RETURN: Pointer to mapped memory. Null on error. + * + * DESCRIPTION: Map physical memory into caller's address space + * + *****************************************************************************/ + +void * +AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS where, + ACPI_SIZE length) +{ + + return (ACPI_TO_POINTER ((ACPI_SIZE) where)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsUnmapMemory + * + * PARAMETERS: where - Logical address of memory to be unmapped + * length - How much memory to unmap + * + * RETURN: None. + * + * DESCRIPTION: Delete a previously created mapping. Where and Length must + * correspond to a previous mapping exactly. + * + *****************************************************************************/ + +void +AcpiOsUnmapMemory ( + void *where, + ACPI_SIZE length) +{ + + return; +} +#endif + + +#ifdef USE_NATIVE_ALLOCATE_ZEROED +/****************************************************************************** + * + * FUNCTION: AcpiOsAllocateZeroed + * + * PARAMETERS: Size - Amount to allocate, in bytes + * + * RETURN: Pointer to the new allocation. Null on error. + * + * DESCRIPTION: Allocate and zero memory. Algorithm is dependent on the OS. + * + *****************************************************************************/ + +void * +AcpiOsAllocateZeroed ( + ACPI_SIZE size) +{ + void *Mem; + + + Mem = (void *) calloc (1, (size_t) size); + return (Mem); +} +#endif + + +#ifdef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: Semaphore stub functions + * + * DESCRIPTION: Stub functions used for single-thread applications that do + * not require semaphore synchronization. Full implementations + * of these functions appear after the stubs. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_HANDLE *OutHandle) +{ + *OutHandle = (ACPI_HANDLE) 1; + return (AE_OK); +} + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_HANDLE Handle) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units, + UINT16 Timeout) +{ + return (AE_OK); +} + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units) +{ + return (AE_OK); +} + +#else +/****************************************************************************** + * + * FUNCTION: AcpiOsCreateSemaphore + * + * PARAMETERS: InitialUnits - Units to be assigned to the new semaphore + * OutHandle - Where a handle will be returned + * + * RETURN: Status + * + * DESCRIPTION: Create an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_HANDLE *OutHandle) +{ + sem_t *Sem; + + + if (!OutHandle) + { + return (AE_BAD_PARAMETER); + } + +#ifdef __APPLE__ + { + static int SemaphoreCount = 0; + char SemaphoreName[32]; + + snprintf (SemaphoreName, sizeof (SemaphoreName), "acpi_sem_%d", + SemaphoreCount++); + printf ("%s\n", SemaphoreName); + Sem = sem_open (SemaphoreName, O_EXCL|O_CREAT, 0755, InitialUnits); + if (!Sem) + { + return (AE_NO_MEMORY); + } + sem_unlink (SemaphoreName); /* This just deletes the name */ + } + +#else + Sem = AcpiOsAllocate (sizeof (sem_t)); + if (!Sem) + { + return (AE_NO_MEMORY); + } + + if (sem_init (Sem, 0, InitialUnits) == -1) + { + AcpiOsFree (Sem); + return (AE_BAD_PARAMETER); + } +#endif + + *OutHandle = (ACPI_HANDLE) Sem; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsDeleteSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * + * RETURN: Status + * + * DESCRIPTION: Delete an OS semaphore + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_HANDLE Handle) +{ + sem_t *Sem = (sem_t *) Handle; + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + +#ifdef __APPLE__ + if (sem_close (Sem) == -1) + { + return (AE_BAD_PARAMETER); + } +#else + if (sem_destroy (Sem) == -1) + { + return (AE_BAD_PARAMETER); + } +#endif + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWaitSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - How many units to wait for + * MsecTimeout - How long to wait (milliseconds) + * + * RETURN: Status + * + * DESCRIPTION: Wait for units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units, + UINT16 MsecTimeout) +{ + ACPI_STATUS Status = AE_OK; + sem_t *Sem = (sem_t *) Handle; + int RetVal; +#ifndef ACPI_USE_ALTERNATE_TIMEOUT + struct timespec Time; +#endif + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + + switch (MsecTimeout) + { + /* + * No Wait: + * -------- + * A zero timeout value indicates that we shouldn't wait - just + * acquire the semaphore if available otherwise return AE_TIME + * (a.k.a. 'would block'). + */ + case 0: + + if (sem_trywait(Sem) == -1) + { + Status = (AE_TIME); + } + break; + + /* Wait Indefinitely */ + + case ACPI_WAIT_FOREVER: + + while (((RetVal = sem_wait (Sem)) == -1) && (errno == EINTR)) + { + continue; /* Restart if interrupted */ + } + if (RetVal != 0) + { + Status = (AE_TIME); + } + break; + + + /* Wait with MsecTimeout */ + + default: + +#ifdef ACPI_USE_ALTERNATE_TIMEOUT + /* + * Alternate timeout mechanism for environments where + * sem_timedwait is not available or does not work properly. + */ + while (MsecTimeout) + { + if (sem_trywait (Sem) == 0) + { + /* Got the semaphore */ + return (AE_OK); + } + + if (MsecTimeout >= 10) + { + MsecTimeout -= 10; + usleep (10 * ACPI_USEC_PER_MSEC); /* ten milliseconds */ + } + else + { + MsecTimeout--; + usleep (ACPI_USEC_PER_MSEC); /* one millisecond */ + } + } + Status = (AE_TIME); +#else + /* + * The interface to sem_timedwait is an absolute time, so we need to + * get the current time, then add in the millisecond Timeout value. + */ + if (clock_gettime (CLOCK_REALTIME, &Time) == -1) + { + perror ("clock_gettime"); + return (AE_TIME); + } + + Time.tv_sec += (MsecTimeout / ACPI_MSEC_PER_SEC); + Time.tv_nsec += ((MsecTimeout % ACPI_MSEC_PER_SEC) * ACPI_NSEC_PER_MSEC); + + /* Handle nanosecond overflow (field must be less than one second) */ + + if (Time.tv_nsec >= ACPI_NSEC_PER_SEC) + { + Time.tv_sec += (Time.tv_nsec / ACPI_NSEC_PER_SEC); + Time.tv_nsec = (Time.tv_nsec % ACPI_NSEC_PER_SEC); + } + + while (((RetVal = sem_timedwait (Sem, &Time)) == -1) && (errno == EINTR)) + { + continue; /* Restart if interrupted */ + + } + + if (RetVal != 0) + { + if (errno != ETIMEDOUT) + { + perror ("sem_timedwait"); + } + Status = (AE_TIME); + } +#endif + break; + } + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignalSemaphore + * + * PARAMETERS: Handle - Handle returned by AcpiOsCreateSemaphore + * Units - Number of units to send + * + * RETURN: Status + * + * DESCRIPTION: Send units + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_HANDLE Handle, + UINT32 Units) +{ + sem_t *Sem = (sem_t *)Handle; + + + if (!Sem) + { + return (AE_BAD_PARAMETER); + } + + if (sem_post (Sem) == -1) + { + return (AE_LIMIT); + } + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + + +/****************************************************************************** + * + * FUNCTION: Spinlock interfaces + * + * DESCRIPTION: Map these interfaces to semaphore interfaces + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsCreateLock ( + ACPI_SPINLOCK *OutHandle) +{ + + return (AcpiOsCreateSemaphore (1, 1, OutHandle)); +} + + +void +AcpiOsDeleteLock ( + ACPI_SPINLOCK Handle) +{ + AcpiOsDeleteSemaphore (Handle); +} + + +ACPI_CPU_FLAGS +AcpiOsAcquireLock ( + ACPI_HANDLE Handle) +{ + AcpiOsWaitSemaphore (Handle, 1, 0xFFFF); + return (0); +} + + +void +AcpiOsReleaseLock ( + ACPI_SPINLOCK Handle, + ACPI_CPU_FLAGS Flags) +{ + AcpiOsSignalSemaphore (Handle, 1); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsInstallInterruptHandler + * + * PARAMETERS: InterruptNumber - Level handler should respond to. + * Isr - Address of the ACPI interrupt handler + * ExceptPtr - Where status is returned + * + * RETURN: Handle to the newly installed handler. + * + * DESCRIPTION: Install an interrupt handler. Used to install the ACPI + * OS-independent handler. + * + *****************************************************************************/ + +UINT32 +AcpiOsInstallInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine, + void *Context) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsRemoveInterruptHandler + * + * PARAMETERS: Handle - Returned when handler was installed + * + * RETURN: Status + * + * DESCRIPTION: Uninstalls an interrupt handler. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsRemoveInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsStall + * + * PARAMETERS: microseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at microsecond granularity + * + *****************************************************************************/ + +void +AcpiOsStall ( + UINT32 microseconds) +{ + /* No-op */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSleep + * + * PARAMETERS: milliseconds - Time to sleep + * + * RETURN: Blocks until sleep is completed. + * + * DESCRIPTION: Sleep at millisecond granularity + * + *****************************************************************************/ + +void +AcpiOsSleep ( + UINT64 milliseconds) +{ + /* No-op */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsGetTimer + * + * PARAMETERS: None + * + * RETURN: Current time in 100 nanosecond units + * + * DESCRIPTION: Get the current system time + * + *****************************************************************************/ + +UINT64 +AcpiOsGetTimer ( + void) +{ + + EFI_STATUS status; + EFI_TIME time; + + if ((status = RS->GetTime(&time, NULL)), EFI_ERROR(status)) { + return 0; + } + + return (((UINT64) time.Hour * 3600ULL + + (UINT64) time.Minute * 60ULL + + (UINT64) time.Second * ACPI_100NSEC_PER_SEC) + + ((UINT64) time.Nanosecond / 100)); +} + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * PciRegister - Device Register + * Value - Buffer where value is placed + * Width - Number of bits + * + * RETURN: Status + * + * DESCRIPTION: Read data from PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 PciRegister, + UINT64 *Value, + UINT32 Width) +{ + + *Value = 0; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePciConfiguration + * + * PARAMETERS: PciId - Seg/Bus/Dev + * PciRegister - Device Register + * Value - Value to be written + * Width - Number of bits + * + * RETURN: Status. + * + * DESCRIPTION: Write data to PCI configuration space + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 PciRegister, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadPort + * + * PARAMETERS: Address - Address of I/O port/register to read + * Value - Where value is placed + * Width - Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width) +{ + + switch (Width) + { + case 8: + + *Value = 0xFF; + break; + + case 16: + + *Value = 0xFFFF; + break; + + case 32: + + *Value = 0xFFFFFFFF; + break; + + default: + + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritePort + * + * PARAMETERS: Address - Address of I/O port/register to write + * Value - Value to write + * Width - Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadMemory + * + * PARAMETERS: Address - Physical Memory Address to read + * Value - Where value is placed + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: Value read from physical memory address. Always returned + * as a 64-bit integer, regardless of the read width. + * + * DESCRIPTION: Read data from a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 *Value, + UINT32 Width) +{ + + switch (Width) + { + case 8: + case 16: + case 32: + case 64: + + *Value = 0; + break; + + default: + + return (AE_BAD_PARAMETER); + } + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWriteMemory + * + * PARAMETERS: Address - Physical Memory Address to write + * Value - Value to write + * Width - Number of bits (8,16,32, or 64) + * + * RETURN: None + * + * DESCRIPTION: Write data to a physical memory address + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 Value, + UINT32 Width) +{ + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsReadable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if readable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for reading + * + *****************************************************************************/ + +BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return (TRUE); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWritable + * + * PARAMETERS: Pointer - Area to be verified + * Length - Size of area + * + * RETURN: TRUE if writable for entire length + * + * DESCRIPTION: Verify that a pointer is valid for writing + * + *****************************************************************************/ + +BOOLEAN +AcpiOsWritable ( + void *Pointer, + ACPI_SIZE Length) +{ + + return (TRUE); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsSignal + * + * PARAMETERS: Function - ACPI A signal function code + * Info - Pointer to function-dependent structure + * + * RETURN: Status + * + * DESCRIPTION: Miscellaneous functions. Example implementation only. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info) +{ + + switch (Function) + { + case ACPI_SIGNAL_FATAL: + + break; + + case ACPI_SIGNAL_BREAKPOINT: + + break; + + default: + + break; + } + + return (AE_OK); +} + +/* Optional multi-thread support */ + +#ifndef ACPI_SINGLE_THREADED +/****************************************************************************** + * + * FUNCTION: AcpiOsGetThreadId + * + * PARAMETERS: None + * + * RETURN: Id of the running thread + * + * DESCRIPTION: Get the ID of the current (running) thread + * + *****************************************************************************/ + +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + pthread_t thread; + + + thread = pthread_self(); + return (ACPI_CAST_PTHREAD_T (thread)); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiOsExecute + * + * PARAMETERS: Type - Type of execution + * Function - Address of the function to execute + * Context - Passed as a parameter to the function + * + * RETURN: Status. + * + * DESCRIPTION: Execute a new thread + * + *****************************************************************************/ + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + pthread_t thread; + int ret; + + + ret = pthread_create (&thread, NULL, (PTHREAD_CALLBACK) Function, Context); + if (ret) + { + AcpiOsPrintf("Create thread failed"); + } + return (0); +} + +#else /* ACPI_SINGLE_THREADED */ +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (1); +} + +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context) +{ + + Function (Context); + + return (AE_OK); +} + +#endif /* ACPI_SINGLE_THREADED */ + + +/****************************************************************************** + * + * FUNCTION: AcpiOsWaitEventsComplete + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Wait for all asynchronous events to complete. This + * implementation does nothing. + * + *****************************************************************************/ + +void +AcpiOsWaitEventsComplete ( + void) +{ + return; +} diff --git a/stand/efi/libacpi/Makefile b/stand/efi/libacpi/Makefile new file mode 100644 index 00000000000000..c74c9126296dcc --- /dev/null +++ b/stand/efi/libacpi/Makefile @@ -0,0 +1,60 @@ +.include + +LIB= acpi + +SRCS+= acpi_detect.c + +CFLAGS+= -I${EFISRC}/include +CFLAGS+= -I${EFISRC}/include/${MACHINE} +CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include +CFLAGS+= -I${EFISRC}/libacpi + +.if ${MACHINE} == "amd64" && ${DO32:U0} == 0 +CFLAGS+= -DACPI_SINGLE_THREADED \ + -DACPI_USE_NATIVE_RSDP_POINTER \ + -DACPI_USE_NATIVE_MEMORY_MAPPING \ + -DACPI_REDUCED_HARDWARE \ + -DACPI_DEBUG_OUTPUT + +.PATH: ${.CURDIR}/../libefi +.PATH: ${.CURDIR}/acpi +.PATH: ${.CURDIR}/acpi/amd64/Osd +.PATH: ${.CURDIR}/../contrib/dev/acpica/os_specific/service_layers +.PATH: ${SYSDIR}/contrib/dev/acpica/os_specific/service_layers +.PATH: ${SYSDIR}/contrib/dev/acpica/components/tables +.PATH: ${SYSDIR}/contrib/dev/acpica/components/namespace +.PATH: ${SYSDIR}/contrib/dev/acpica/components/utilities +.PATH: ${SYSDIR}/contrib/dev/acpica/components/dispatcher +.PATH: ${SYSDIR}/contrib/dev/acpica/components/executer +.PATH: ${SYSDIR}/contrib/dev/acpica/components/hardware +.PATH: ${SYSDIR}/contrib/dev/acpica/components/events +.PATH: ${SYSDIR}/contrib/dev/acpica/components/parser + +SRCS+= libefi.c OsdMemory.c osunixxf.c utinit.c utglobal.c utresrc.c utlock.c \ + utownerid.c utcopy.c uthex.c utmath.c utstrsuppt.c utstrtoul64.c \ + utpredef.c uterror.c uteval.c utids.c utbuffer.c utmisc.c utalloc.c \ + utxferror.c utexcep.c utaddress.c utascii.c utcache.c utcksum.c \ + utdebug.c utdecode.c utdelete.c utmutex.c utobject.c utosi.c \ + utstring.c utxfinit.c utnonansi.c utstate.c tbdata.c tbxfload.c \ + tbfadt.c tbinstal.c tbprint.c tbutils.c tbxface.c tbxfroot.c \ + tbfind.c nsxfobj.c nsxfeval.c nsinit.c nsparse.c nsload.c \ + nsrepair2.c nsconvert.c nsrepair.c nsprepkg.c nsarguments.c nseval.c \ + nsxfname.c nsdump.c nswalk.c nssearch.c nsnames.c nsutils.c \ + nsaccess.c nsalloc.c nsobject.c nspredef.c dsinit.c dsfield.c \ + dspkginit.c dsopcode.c dsdebug.c dsmethod.c dscontrol.c dsobject.c \ + dsutils.c dswexec.c dswload2.c dswload.c dsmthdat.c dswstate.c \ + dsargs.c dswscope.c exregion.c exfldio.c exserial.c exstorob.c \ + exstoren.c exdebug.c exmutex.c exconcat.c exmisc.c exconfig.c \ + excreate.c exoparg6.c exoparg3.c exoparg2.c exoparg1.c exdump.c \ + exprep.c exresop.c exsystem.c exnames.c exresolv.c exstore.c \ + exfield.c exconvrt.c exresnte.c exutils.c extrace.c hwpci.c \ + hwregs.c hwxface.c hwvalid.c hwacpi.c evmisc.c evregion.c evrgnini.c \ + evxface.c evevent.c evxfevnt.c evhandler.c evxfregn.c psobject.c \ + psloop.c pstree.c pswalk.c psopinfo.c psscope.c psutils.c psargs.c \ + psparse.c psxface.c psopcode.c init_acpi.c + +CFLAGS+= -I${EFISRC}/libacpi/acpi/include + +.endif # amd64 + +.include diff --git a/stand/efi/libacpi/README.md b/stand/efi/libacpi/README.md new file mode 100644 index 00000000000000..9f443463b6cc9a --- /dev/null +++ b/stand/efi/libacpi/README.md @@ -0,0 +1,64 @@ +# Google Summer of Code 2025 @ FreeBSD +Mentor: Warner Losh @bsdimp +Student: Kayla (Kat) Powell @kpowkitty +--------------- +## ACPI Initialization in Loader with Lua Bindings +Intel's Advanced Configuration and Power Interface (ACPI) brought power management out of the BIOS +and into the operating system. We can make it even more powerful by creating an interface +to script it. Currently, the scripting language of choice in FreeBSD (rather than POSIX `sh`, `bash`, or `awk`) +is Lua. Therefore, this project aims to initialize a portion of ACPI in the FreeBSD bootloader, with respect +to its storage, memory, and stdlib constraints, so we can enumerate and evaluate objects on the device trees to +provide an interface to Lua. + +## Milestones +[x] `OsdMemory.c` for `amd64` (`arm64` postponed) +[x] `AcpiInitializeSubsystem` +[x] `AcpiInitializeTables` +[x] `AcpiEnableSubsystem` in reduced hardware mode, with events enabled +[x] `AcpiLoadTables` +[x] `AcpiWalkNamespace` +[x] `AcpiEvaluateObject` +[x] ACPICA initialized in loader for `amd64` +[x] lacpi_object.c (V1) + -- V1: Users can evaluate objects +[x] lacpi_data.c (V1) + -- V1: Users can attach, get, detach data from nodes +[x] lacpi_walk.c (V1) + -- V1: Walk and read nodes off the namespace + -- V2: Namespace format -- TBR + -- V3: Strategies for walking the namespace -- TBR +[x] Man page update + +**Future goals of this project include arm64 compat and extending the interface.** + +### For more information, please consult these resources: +[ACPI Lua Bindings FreeBSD project wiki page](https://wiki.freebsd.org/SummerOfCode2025Projects/ACPI%20Initialization%20in%20Loader%20With%20Lua%20Bindings) +[Write-up](https://kmpow.com/content/gsoc-writeup) + +--------------- + +## Building +This project requires an amd64 UEFI FreeBSD system. + +The current working version of this project is found on branch `acpi_init`. + +1. Clone the repo +``` +$ git clone git@github.com:kpowkitty/freebsd-src.git +$ git checkout acpi_init +``` + +2. Build the necessary dependencies and install the loader image +``` +$ cd stand/efi +# make -j $MAX_JOBS && make install +``` + +3. Reboot +``` +# shutdown -r now +``` + +## System Recovery +In general cases, to recover your system, you need to mount your drive +on a live iso and replace your drive's `loader.efi` with the live iso image's `loader.efi`. diff --git a/stand/efi/libacpi/acpi/amd64/Osd/OsdMemory.c b/stand/efi/libacpi/acpi/amd64/Osd/OsdMemory.c new file mode 100644 index 00000000000000..646e518cf9bebc --- /dev/null +++ b/stand/efi/libacpi/acpi/amd64/Osd/OsdMemory.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2025 Kayla Powell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +void * +AcpiOsAllocate(ACPI_SIZE Size) +{ + return (malloc(Size)); +} + +void +AcpiOsFree(void *Memory) +{ + free(Memory); +} + +void * +AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) +{ + return (void *)(PhysicalAddress); +} + +void +AcpiOsUnmapMemory(void *LogicalAddress, ACPI_SIZE Length) +{ + /* No-op as we never mapped any memory. */ +} + +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void) +{ + if (!rsdp) { + return (0); + } + + return (ACPI_PHYSICAL_ADDRESS)(uintptr_t)(rsdp); +} diff --git a/stand/efi/libacpi/acpi/include/init_acpi.h b/stand/efi/libacpi/acpi/include/init_acpi.h new file mode 100644 index 00000000000000..3c65e5cd364041 --- /dev/null +++ b/stand/efi/libacpi/acpi/include/init_acpi.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2025 Kayla Powell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef INIT_ACPI_H +#define INIT_ACPI_H + +#include +#include +#include + +#define ACPI_LOADER 0x00020000 + +ACPI_STATUS acpi_Startup(void); +int init_acpi(void); +int acpi_is_initialized(void); + +#endif /* ACPI_H */ diff --git a/stand/efi/libacpi/acpi/init_acpi.c b/stand/efi/libacpi/acpi/init_acpi.c new file mode 100644 index 00000000000000..f18681f0588036 --- /dev/null +++ b/stand/efi/libacpi/acpi/init_acpi.c @@ -0,0 +1,132 @@ +/*- + * Copyright (c) 2025 Kayla Powell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _COMPONENT ACPI_LOADER +ACPI_MODULE_NAME("init_acpi"); + +/* Singleton protection. */ +static int acpi_inited = 0; + +/* + * Initialize a smaller subset of the ACPI subsystem in the + * loader. This subset is enough for users to evaluate + * objects on the namespace, and includes event management. + * + * This function brings up the ACPICA core in four stages: + * 1. Initialize the ACPICA subsystem. + * 2. Initialize and validate ACPI root tables. + * 3. Enable the subsystem (without full hardware mode, but events + * enabled). + * 4. Load ACPI tables into the namespace. + * + * Returns ACPI_STATUS; failure indicates issue reading RSDT/XSDT. + * Please refer to your motherboard manual to verify ACPI support. + */ +ACPI_STATUS +acpi_Startup(void) +{ + ACPI_STATUS status; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + /* Initialize the ACPICA subsystem. */ + if (ACPI_FAILURE(status = AcpiInitializeSubsystem())) { + printf("ACPI: Could not initialize Subsystem: %s\n", + AcpiFormatException(status)); + return_VALUE(status); + } + + /* Initialize the ACPICA tables. */ + if (ACPI_FAILURE(status = AcpiInitializeTables(NULL, 2, TRUE))) { + printf("ACPI: Table initialisation failed: %s\n", + AcpiFormatException(status)); + return_VALUE(status); + } + + /* Enable the ACPI subsystem. */ + uint32_t flags = ACPI_REDUCED_HARDWARE | ACPI_NO_ACPI_ENABLE; + if (ACPI_FAILURE(status = AcpiEnableSubsystem(flags))) { + printf("ACPI: Enable subsystem failed: %s\n", + AcpiFormatException(status)); + return_VALUE(status); + } + + /* Create the ACPI namespace from ACPI tables. */ + if (ACPI_FAILURE(status = AcpiLoadTables())) { + printf("ACPI: Load tables failed: %s\n", + AcpiFormatException(status)); + return_VALUE(status); + } + + return_VALUE(status); +} + +/* + * Initialize ACPI once for the loader. + * + * This is a singleton entry point. Safe to call multiple times; + * subsequent calls will return success immediately. + * + * Returns 0 on success, ENXIO if ACPI could not be initialized. + */ +int +init_acpi(void) +{ + ACPI_STATUS status; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + if (acpi_inited) { + return (0); + } + + if (ACPI_FAILURE(status = acpi_Startup())) { + printf("ACPI: Loader initialization failed with status %s\n", + AcpiFormatException(status)); + return (ENXIO); + } + + acpi_inited = 1; + + return (0); +} + +/* + * Confirm ACPI initialization. + */ +int +acpi_is_initialized(void) +{ + return (acpi_inited); +} diff --git a/stand/efi/libacpi/acpi_detect.c b/stand/efi/libacpi/acpi_detect.c new file mode 100644 index 00000000000000..7895636b4d68ae --- /dev/null +++ b/stand/efi/libacpi/acpi_detect.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2014 Ed Maste + * Copyright (c) 2025 Kayla Powell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "acpi_detect.h" + +/* For ACPI rsdp discovery. */ +EFI_GUID acpi = ACPI_TABLE_GUID; +EFI_GUID acpi20 = ACPI_20_TABLE_GUID; +ACPI_TABLE_RSDP *rsdp; + +void +acpi_detect(void) +{ + char buf[24]; + int revision; + + feature_enable(FEATURE_EARLY_ACPI); + if ((rsdp = efi_get_table(&acpi20)) == NULL) + if ((rsdp = efi_get_table(&acpi)) == NULL) + return; + + sprintf(buf, "0x%016"PRIxPTR, (uintptr_t)rsdp); + setenv("acpi.rsdp", buf, 1); + revision = rsdp->Revision; + if (revision == 0) + revision = 1; + sprintf(buf, "%d", revision); + setenv("acpi.revision", buf, 1); + strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); + buf[sizeof(rsdp->OemId)] = '\0'; + setenv("acpi.oem", buf, 1); + sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); + setenv("acpi.rsdt", buf, 1); + if (revision >= 2) { + /* XXX extended checksum? */ + sprintf(buf, "0x%016llx", + (unsigned long long)rsdp->XsdtPhysicalAddress); + setenv("acpi.xsdt", buf, 1); + sprintf(buf, "%d", rsdp->Length); + setenv("acpi.xsdt_length", buf, 1); + } +} diff --git a/stand/efi/libacpi/acpi_detect.h b/stand/efi/libacpi/acpi_detect.h new file mode 100644 index 00000000000000..246e790be9fbdf --- /dev/null +++ b/stand/efi/libacpi/acpi_detect.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Kayla Powell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACPI_DETECT_H +#define ACPI_DETECT_H + +#include +#include + +struct ACPI_TABLE_RSDP; // forward declaration + +extern EFI_GUID acpi; +extern EFI_GUID acpi20; +extern ACPI_TABLE_RSDP *rsdp; + +void acpi_detect(void); + +#endif diff --git a/stand/efi/libacpi32/Makefile b/stand/efi/libacpi32/Makefile new file mode 100644 index 00000000000000..659a9f7000d9e3 --- /dev/null +++ b/stand/efi/libacpi32/Makefile @@ -0,0 +1,4 @@ +DO32=1 + +.PATH: ${.CURDIR}/../libacpi +.include "${.CURDIR}/../libacpi/Makefile" diff --git a/stand/efi/loader/Makefile b/stand/efi/loader/Makefile index ae2ffc475730f7..4f51d4898cd8ba 100644 --- a/stand/efi/loader/Makefile +++ b/stand/efi/loader/Makefile @@ -66,9 +66,14 @@ CFLAGS+= -I${.CURDIR}/arch/${__arch} CFLAGS+= -I${EFISRC}/include CFLAGS+= -I${EFISRC}/include/${__arch} CFLAGS+= -I${SYSDIR}/contrib/dev/acpica/include +CFLAGS+= -I${EFISRC}/libacpi CFLAGS+= -I${BOOTSRC}/i386/libi386 CFLAGS+= -DEFI +.if ${MACHINE} == "amd64" && ${DO32:U0} == 0 +CFLAGS+= -I${EFISRC}/libacpi/acpi/include +.endif + .if defined(HAVE_FDT) && ${MK_FDT} != "no" .include "${BOOTSRC}/fdt.mk" LIBEFI_FDT= ${BOOTOBJ}/efi/fdt/libefi_fdt.a @@ -136,13 +141,17 @@ ${LOADER}.efi: ${PROG} LIBEFI= ${BOOTOBJ}/efi/libefi/libefi.a LIBEFI32= ${BOOTOBJ}/efi/libefi32/libefi.a +LIBACPI= ${BOOTOBJ}/efi/libacpi/libacpi.a +LIBACPI32= ${BOOTOBJ}/efi/libacpi32/libacpi.a .if ${__arch} == "i386" -DPADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32} ${LDSCRIPT} -LDADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32} +DPADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32} ${LIBACPI32} ${LDSCRIPT} +LDADD= ${LDR_INTERP32} ${LIBEFI32} ${LIBSA32} ${LIBACPI32} .else -DPADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA} ${LDSCRIPT} -LDADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA} +DPADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA} \ + ${LIBACPI} ${LDSCRIPT} +LDADD= ${LDR_INTERP} ${LIBEFI} ${LIBSAFDT} ${LIBEFI_FDT} ${LIBSA} \ + ${LIBACPI} .endif .include diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 4366763684473a..15201c51a53ab5 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -66,8 +66,15 @@ #include "platform/acfreebsd.h" #include "acconfig.h" #define ACPI_SYSTEM_XFACE + +#if defined(__amd64__) +#include +#else +#include +#endif #include "actypes.h" #include "actbl.h" +#include #include "loader_efi.h" @@ -83,8 +90,6 @@ struct arch_switch archsw = { /* MI/MD interface boundary */ .arch_zfs_probe = efi_zfs_probe, }; -EFI_GUID acpi = ACPI_TABLE_GUID; -EFI_GUID acpi20 = ACPI_20_TABLE_GUID; EFI_GUID devid = DEVICE_PATH_PROTOCOL; EFI_GUID imgid = LOADED_IMAGE_PROTOCOL; EFI_GUID mps = MPS_TABLE_GUID; @@ -120,11 +125,6 @@ UINT16 boot_current; */ EFI_LOADED_IMAGE *boot_img; -/* - * RSDP base table. - */ -ACPI_TABLE_RSDP *rsdp; - static bool has_keyboard(void) { @@ -1129,39 +1129,6 @@ ptov(uintptr_t x) return ((caddr_t)x); } -static void -acpi_detect(void) -{ - char buf[24]; - int revision; - - feature_enable(FEATURE_EARLY_ACPI); - if ((rsdp = efi_get_table(&acpi20)) == NULL) - if ((rsdp = efi_get_table(&acpi)) == NULL) - return; - - sprintf(buf, "0x%016"PRIxPTR, (uintptr_t)rsdp); - setenv("acpi.rsdp", buf, 1); - revision = rsdp->Revision; - if (revision == 0) - revision = 1; - sprintf(buf, "%d", revision); - setenv("acpi.revision", buf, 1); - strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); - buf[sizeof(rsdp->OemId)] = '\0'; - setenv("acpi.oem", buf, 1); - sprintf(buf, "0x%016x", rsdp->RsdtPhysicalAddress); - setenv("acpi.rsdt", buf, 1); - if (revision >= 2) { - /* XXX extended checksum? */ - sprintf(buf, "0x%016llx", - (unsigned long long)rsdp->XsdtPhysicalAddress); - setenv("acpi.xsdt", buf, 1); - sprintf(buf, "%d", rsdp->Length); - setenv("acpi.xsdt_length", buf, 1); - } -} - static void efi_smbios_detect(void) { @@ -1211,6 +1178,7 @@ main(int argc, CHAR16 *argv[]) char boot_info[4096]; char buf[32]; bool uefi_boot_mgr; + int ret = 0; #if !defined(__arm__) efi_smbios_detect(); @@ -1267,6 +1235,13 @@ main(int argc, CHAR16 *argv[]) devinit(); +#if defined(__amd64__) + /* Initialize ACPI Subsystem and Tables. */ + if ((ret = init_acpi()) != 0) { + printf("Failed to initialize ACPI\n."); + } +#endif + /* * Detect console settings two different ways: one via the command * args (eg -h) or via the UEFI ConOut variable. diff --git a/sys/contrib/dev/acpica/components/events/evxface.c b/sys/contrib/dev/acpica/components/events/evxface.c index 54634c61e517c1..6ad67369e76df5 100644 --- a/sys/contrib/dev/acpica/components/events/evxface.c +++ b/sys/contrib/dev/acpica/components/events/evxface.c @@ -175,7 +175,7 @@ AcpiEvInstallGpeHandler ( #endif - +#ifndef _STANDALONE /******************************************************************************* * * FUNCTION: AcpiInstallNotifyHandler @@ -517,6 +517,7 @@ AcpiRemoveNotifyHandler ( ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) +#endif /* !_STANDALONE */ /******************************************************************************* * @@ -794,7 +795,7 @@ AcpiInstallGlobalEventHandler ( ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) - +#ifndef _STANDALONE /******************************************************************************* * * FUNCTION: AcpiInstallFixedEventHandler @@ -942,6 +943,7 @@ AcpiRemoveFixedEventHandler ( ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) +#endif /* !_STANDALONE */ /******************************************************************************* * diff --git a/sys/contrib/dev/acpica/components/hardware/hwxface.c b/sys/contrib/dev/acpica/components/hardware/hwxface.c index 5f645617cbcefe..c5f4d31273d927 100644 --- a/sys/contrib/dev/acpica/components/hardware/hwxface.c +++ b/sys/contrib/dev/acpica/components/hardware/hwxface.c @@ -476,7 +476,7 @@ ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister) #endif /* !ACPI_REDUCED_HARDWARE */ - +#ifndef _STANDALONE /******************************************************************************* * * FUNCTION: AcpiGetSleepTypeData @@ -644,3 +644,5 @@ AcpiGetSleepTypeData ( } ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) + +#endif /* !_STANDALONE */ diff --git a/sys/contrib/dev/acpica/components/utilities/utdelete.c b/sys/contrib/dev/acpica/components/utilities/utdelete.c index e88cc736990b32..38b47ccb03cd85 100644 --- a/sys/contrib/dev/acpica/components/utilities/utdelete.c +++ b/sys/contrib/dev/acpica/components/utilities/utdelete.c @@ -261,10 +261,12 @@ AcpiUtDeleteInternalObj ( */ case ACPI_TYPE_DEVICE: +#ifndef _STANDALONE if (Object->Device.GpeBlock) { (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock); } +#endif ACPI_FALLTHROUGH; diff --git a/sys/contrib/dev/acpica/components/utilities/utinit.c b/sys/contrib/dev/acpica/components/utilities/utinit.c index b5a4b7e7d936f7..5e051c34dee3a1 100644 --- a/sys/contrib/dev/acpica/components/utilities/utinit.c +++ b/sys/contrib/dev/acpica/components/utilities/utinit.c @@ -429,7 +429,7 @@ AcpiUtSubsystemShutdown ( AcpiGbl_StartupFlags = 0; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); -#ifndef ACPI_ASL_COMPILER +#if !defined(ACPI_ASL_COMPILER) && !defined(_STANDALONE) /* Close the AcpiEvent Handling */ diff --git a/sys/contrib/dev/acpica/components/utilities/utxfinit.c b/sys/contrib/dev/acpica/components/utilities/utxfinit.c index f295471031d0e9..3b5ff80869bde1 100644 --- a/sys/contrib/dev/acpica/components/utilities/utxfinit.c +++ b/sys/contrib/dev/acpica/components/utilities/utxfinit.c @@ -358,6 +358,7 @@ AcpiEnableSubsystem ( ACPI_EXPORT_SYMBOL_INIT (AcpiEnableSubsystem) +#ifndef _STANDALONE /******************************************************************************* * * FUNCTION: AcpiInitializeObjects @@ -428,3 +429,5 @@ AcpiInitializeObjects ( } ACPI_EXPORT_SYMBOL_INIT (AcpiInitializeObjects) + +#endif /* !_STANDALONE */ diff --git a/sys/contrib/dev/acpica/include/accommon.h b/sys/contrib/dev/acpica/include/accommon.h index 10a39803842b04..b032d3c03a4ecb 100644 --- a/sys/contrib/dev/acpica/include/accommon.h +++ b/sys/contrib/dev/acpica/include/accommon.h @@ -170,6 +170,9 @@ #ifndef ACPI_USE_SYSTEM_CLIBRARY #include /* C library interfaces */ #endif /* !ACPI_USE_SYSTEM_CLIBRARY */ +#ifdef _STANDALONE +#include +#endif #endif /* __ACCOMMON_H__ */