1 /****************************************************************************** 2 * 3 * Module Name: antables - ACPI table setup/install for AcpiNames utility 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpinames.h" 45 46 #define _COMPONENT ACPI_TOOLS 47 ACPI_MODULE_NAME ("antables") 48 49 /* Local prototypes */ 50 51 ACPI_PHYSICAL_ADDRESS 52 AeLocalGetRootPointer ( 53 void); 54 55 /* Non-AML tables that are constructed locally and installed */ 56 57 static ACPI_TABLE_RSDP LocalRSDP; 58 static ACPI_TABLE_FACS LocalFACS; 59 60 /* 61 * We need a local FADT so that the hardware subcomponent will function, 62 * even though the underlying OSD HW access functions don't do anything. 63 */ 64 static ACPI_TABLE_FADT LocalFADT; 65 66 /* 67 * Use XSDT so that both 32- and 64-bit versions of this utility will 68 * function automatically. 69 */ 70 static ACPI_TABLE_XSDT *LocalXSDT; 71 72 #define BASE_XSDT_TABLES 1 73 #define BASE_XSDT_SIZE (sizeof (ACPI_TABLE_XSDT) + \ 74 ((BASE_XSDT_TABLES -1) * sizeof (UINT64))) 75 76 ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES]; 77 78 79 /****************************************************************************** 80 * 81 * FUNCTION: AeBuildLocalTables 82 * 83 * PARAMETERS: TableCount - Number of tables on the command line 84 * TableList - List of actual tables from files 85 * 86 * RETURN: Status 87 * 88 * DESCRIPTION: Build a complete ACPI table chain, with a local RSDP, XSDT, 89 * FADT, FACS, and the input DSDT/SSDT. 90 * 91 *****************************************************************************/ 92 93 ACPI_STATUS 94 AeBuildLocalTables ( 95 UINT32 TableCount, 96 AE_TABLE_DESC *TableList) 97 { 98 ACPI_PHYSICAL_ADDRESS DsdtAddress = 0; 99 UINT32 XsdtSize; 100 AE_TABLE_DESC *NextTable; 101 UINT32 NextIndex; 102 ACPI_TABLE_FADT *ExternalFadt = NULL; 103 104 105 /* 106 * Update the table count. For DSDT, it is not put into the XSDT. For 107 * FADT, this is already accounted for since we usually install a 108 * local FADT. 109 */ 110 NextTable = TableList; 111 while (NextTable) 112 { 113 if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) || 114 ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) 115 { 116 TableCount--; 117 } 118 NextTable = NextTable->Next; 119 } 120 121 XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64)); 122 123 /* Build an XSDT */ 124 125 LocalXSDT = AcpiOsAllocate (XsdtSize); 126 if (!LocalXSDT) 127 { 128 return (AE_NO_MEMORY); 129 } 130 131 ACPI_MEMSET (LocalXSDT, 0, XsdtSize); 132 ACPI_MOVE_NAME (LocalXSDT->Header.Signature, ACPI_SIG_XSDT); 133 LocalXSDT->Header.Length = XsdtSize; 134 LocalXSDT->Header.Revision = 1; 135 136 LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT); 137 138 /* 139 * Install the user tables. The DSDT must be installed in the FADT. 140 * All other tables are installed directly into the XSDT. 141 */ 142 NextIndex = BASE_XSDT_TABLES; 143 NextTable = TableList; 144 while (NextTable) 145 { 146 /* 147 * Incoming DSDT or FADT are special cases. All other tables are 148 * just immediately installed into the XSDT. 149 */ 150 if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT)) 151 { 152 if (DsdtAddress) 153 { 154 printf ("Already found a DSDT, only one allowed\n"); 155 return (AE_ALREADY_EXISTS); 156 } 157 158 /* The incoming user table is a DSDT */ 159 160 DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table); 161 } 162 else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT)) 163 { 164 ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table); 165 LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); 166 } 167 else 168 { 169 /* Install the table in the XSDT */ 170 171 LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table); 172 NextIndex++; 173 } 174 175 NextTable = NextTable->Next; 176 } 177 178 /* Build an RSDP */ 179 180 ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP)); 181 ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature); 182 ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6); 183 LocalRSDP.Revision = 2; 184 LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT); 185 LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT); 186 187 /* Set checksums for both XSDT and RSDP */ 188 189 LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum ( 190 (void *) LocalXSDT, LocalXSDT->Header.Length); 191 LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum ( 192 (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH); 193 194 if (!DsdtAddress) 195 { 196 return (AE_SUPPORT); 197 } 198 199 if (ExternalFadt) 200 { 201 /* 202 * Use the external FADT, but we must update the DSDT/FACS addresses 203 * as well as the checksum 204 */ 205 ExternalFadt->Dsdt = DsdtAddress; 206 ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); 207 208 if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt)) 209 { 210 ExternalFadt->XDsdt = DsdtAddress; 211 ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); 212 } 213 /* Complete the FADT with the checksum */ 214 215 ExternalFadt->Header.Checksum = 0; 216 ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum ( 217 (void *) ExternalFadt, ExternalFadt->Header.Length); 218 } 219 else 220 { 221 /* 222 * Build a local FADT so we can test the hardware/event init 223 */ 224 ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT)); 225 ACPI_MOVE_NAME (LocalFADT.Header.Signature, ACPI_SIG_FADT); 226 227 /* Setup FADT header and DSDT/FACS addresses */ 228 229 LocalFADT.Dsdt = 0; 230 LocalFADT.Facs = 0; 231 232 LocalFADT.XDsdt = DsdtAddress; 233 LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS); 234 235 LocalFADT.Header.Revision = 3; 236 LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT); 237 238 /* Miscellaneous FADT fields */ 239 240 LocalFADT.Gpe0BlockLength = 16; 241 LocalFADT.Gpe0Block = 0x00001234; 242 243 LocalFADT.Gpe1BlockLength = 6; 244 LocalFADT.Gpe1Block = 0x00005678; 245 LocalFADT.Gpe1Base = 96; 246 247 LocalFADT.Pm1EventLength = 4; 248 LocalFADT.Pm1aEventBlock = 0x00001aaa; 249 LocalFADT.Pm1bEventBlock = 0x00001bbb; 250 251 LocalFADT.Pm1ControlLength = 2; 252 LocalFADT.Pm1aControlBlock = 0xB0; 253 254 LocalFADT.PmTimerLength = 4; 255 LocalFADT.PmTimerBlock = 0xA0; 256 257 LocalFADT.Pm2ControlBlock = 0xC0; 258 LocalFADT.Pm2ControlLength = 1; 259 260 /* Setup one example X-64 field */ 261 262 LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO; 263 LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock; 264 LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength); 265 266 /* Complete the FADT with the checksum */ 267 268 LocalFADT.Header.Checksum = 0; 269 LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum ( 270 (void *) &LocalFADT, LocalFADT.Header.Length); 271 } 272 273 /* Build a FACS */ 274 275 ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS)); 276 ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS); 277 278 LocalFACS.Length = sizeof (ACPI_TABLE_FACS); 279 LocalFACS.GlobalLock = 0x11AA0011; 280 281 return (AE_OK); 282 } 283 284 285 /****************************************************************************** 286 * 287 * FUNCTION: AeLocalGetRootPointer 288 * 289 * PARAMETERS: None 290 * 291 * RETURN: Address of the RSDP 292 * 293 * DESCRIPTION: Return a local RSDP, used to dynamically load tables via the 294 * standard ACPI mechanism. 295 * 296 *****************************************************************************/ 297 298 ACPI_PHYSICAL_ADDRESS 299 AeLocalGetRootPointer ( 300 void) 301 { 302 303 return ((ACPI_PHYSICAL_ADDRESS) &LocalRSDP); 304 }