xref: /netbsd-src/sys/external/bsd/acpica/dist/tools/acpiexec/aeinitfile.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1 /******************************************************************************
2  *
3  * Module Name: aeinitfile - Support for optional initialization file
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 "aecommon.h"
45 #include "acdispat.h"
46 #include "acnamesp.h"
47 
48 
49 #define _COMPONENT          ACPI_TOOLS
50         ACPI_MODULE_NAME    ("aeinitfile")
51 
52 
53 #define AE_FILE_BUFFER_SIZE     512
54 
55 static char                 LineBuffer[AE_FILE_BUFFER_SIZE];
56 static char                 NameBuffer[AE_FILE_BUFFER_SIZE];
57 static FILE                 *InitFile;
58 
59 
60 /******************************************************************************
61  *
62  * FUNCTION:    AeOpenInitializationFile
63  *
64  * PARAMETERS:  Filename            - Path to the init file
65  *
66  * RETURN:      Status
67  *
68  * DESCRIPTION: Open the initialization file for the -fi option
69  *
70  *****************************************************************************/
71 
72 int
AeOpenInitializationFile(char * Filename)73 AeOpenInitializationFile (
74     char                    *Filename)
75 {
76 
77     InitFile = fopen (Filename, "r");
78     if (!InitFile)
79     {
80         fprintf (stderr,
81             "Could not open initialization file: %s\n", Filename);
82         return (-1);
83     }
84 
85     AcpiOsPrintf ("Opened initialization file [%s]\n", Filename);
86     return (0);
87 }
88 
89 
90 /******************************************************************************
91  *
92  * FUNCTION:    AeProcessInitFile
93  *
94  * PARAMETERS:  None
95  *
96  * RETURN:      None
97  *
98  * DESCRIPTION: Read the initialization file and perform all namespace
99  *              initializations. AcpiGbl_InitEntries will be used for all
100  *              object initialization.
101  *
102  * NOTE:        The format of the file is multiple lines, each of format:
103  *                  <ACPI-pathname> <New Value>
104  *
105  *****************************************************************************/
106 
107 ACPI_STATUS
AeProcessInitFile(void)108 AeProcessInitFile (
109     void)
110 {
111     ACPI_WALK_STATE         *WalkState;
112     UINT64                  idx;
113     ACPI_STATUS             Status = AE_OK;
114     char                    *Token;
115     char                    *ValueBuffer;
116     char                    *TempNameBuffer;
117     ACPI_OBJECT_TYPE        Type;
118     ACPI_OBJECT             TempObject;
119 
120 
121     if (!InitFile)
122     {
123         return (AE_OK);
124     }
125 
126     /* Create needed objects to be reused for each init entry */
127 
128     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
129     NameBuffer[0] = '\\';
130     NameBuffer[1] = 0;
131 
132     while (fgets (LineBuffer, AE_FILE_BUFFER_SIZE, InitFile) != NULL)
133     {
134         ++AcpiGbl_InitFileLineCount;
135     }
136     rewind (InitFile);
137 
138     /*
139      * Allocate and populate the Gbl_InitEntries array
140      */
141     AcpiGbl_InitEntries =
142         AcpiOsAllocateZeroed (sizeof (INIT_FILE_ENTRY) * AcpiGbl_InitFileLineCount);
143     for (idx = 0; fgets (LineBuffer, AE_FILE_BUFFER_SIZE, InitFile); ++idx)
144     {
145         TempNameBuffer = AcpiDbGetNextToken (LineBuffer, &Token, &Type);
146         if (!TempNameBuffer)
147         {
148             AcpiGbl_InitEntries[idx].Name = NULL;
149             continue;
150         }
151 
152         if (LineBuffer[0] == '\\')
153         {
154             strcpy (NameBuffer, TempNameBuffer);
155         }
156         else
157         {
158             /* Add a root prefix if not present in the string */
159 
160             strcpy (NameBuffer + 1, TempNameBuffer);
161         }
162 
163         AcpiNsNormalizePathname (NameBuffer);
164         AcpiGbl_InitEntries[idx].Name =
165             AcpiOsAllocateZeroed (strnlen (NameBuffer, AE_FILE_BUFFER_SIZE) + 1);
166         strcpy (AcpiGbl_InitEntries[idx].Name, NameBuffer);
167 
168         ValueBuffer = AcpiDbGetNextToken (Token, &Token, &Type);
169         if (!ValueBuffer)
170         {
171             AcpiGbl_InitEntries[idx].Value = NULL;
172             continue;
173         }
174 
175         AcpiGbl_InitEntries[idx].Value =
176             AcpiOsAllocateZeroed (strnlen (ValueBuffer, AE_FILE_BUFFER_SIZE) + 1);
177         strcpy (AcpiGbl_InitEntries[idx].Value, ValueBuffer);
178 
179         if (Type == ACPI_TYPE_FIELD_UNIT)
180         {
181             Status = AcpiDbConvertToObject (ACPI_TYPE_BUFFER, ValueBuffer,
182                 &TempObject);
183         }
184         else
185         {
186             Status = AcpiDbConvertToObject (Type, ValueBuffer, &TempObject);
187         }
188 
189         if (ACPI_FAILURE (Status))
190         {
191             AcpiOsPrintf ("%s[%s]: %s\n", NameBuffer, AcpiUtGetTypeName (Type),
192                 AcpiFormatException (Status));
193             goto CleanupAndExit;
194         }
195 
196         Status = AcpiUtCopyEobjectToIobject (&TempObject,
197             &AcpiGbl_InitEntries[idx].ObjDesc);
198 
199         /* Cleanup the external object created by DbConvertToObject above */
200 
201         if (ACPI_SUCCESS (Status))
202         {
203             if (Type == ACPI_TYPE_BUFFER || Type == ACPI_TYPE_FIELD_UNIT)
204             {
205                 ACPI_FREE (TempObject.Buffer.Pointer);
206             }
207             else if (Type == ACPI_TYPE_PACKAGE)
208             {
209                 AcpiDbDeleteObjects (1, &TempObject);
210             }
211         }
212         else
213         {
214             AcpiOsPrintf ("%s[%s]: %s\n", NameBuffer, AcpiUtGetTypeName (Type),
215                 AcpiFormatException (Status));
216             goto CleanupAndExit;
217         }
218 
219         /*
220          * Initialize the namespace node with the value found in the init file.
221          */
222         AcpiOsPrintf ("Namespace object init from file: %16s, Value \"%s\", Type %s\n",
223             AcpiGbl_InitEntries[idx].Name, AcpiGbl_InitEntries[idx].Value, AcpiUtGetTypeName (Type));
224     }
225 
226     /* Cleanup */
227 
228 CleanupAndExit:
229     fclose (InitFile);
230     AcpiDsDeleteWalkState (WalkState);
231     return (Status);
232 }
233 
234 
235 /******************************************************************************
236  *
237  * FUNCTION:    AeLookupInitFileEntry
238  *
239  * PARAMETERS:  Pathname            - AML namepath in external format
240  *              ObjDesc             - Where the object is returned if it exists
241  *
242  * RETURN:      Status. AE_OK if a match was found
243  *
244  * DESCRIPTION: Search the init file for a particular name and its value.
245  *
246  *****************************************************************************/
247 
248 ACPI_STATUS
AeLookupInitFileEntry(char * Pathname,ACPI_OPERAND_OBJECT ** ObjDesc)249 AeLookupInitFileEntry (
250     char                    *Pathname,
251     ACPI_OPERAND_OBJECT     **ObjDesc)
252 {
253     UINT32                  i;
254 
255     ACPI_FUNCTION_TRACE (AeLookupInitFileEntry);
256 
257     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Lookup: %s\n", Pathname));
258 
259     if (!AcpiGbl_InitEntries)
260     {
261         return (AE_NOT_FOUND);
262     }
263 
264     AcpiNsNormalizePathname (Pathname);
265 
266     for (i = 0; i < AcpiGbl_InitFileLineCount; ++i)
267     {
268         if (AcpiGbl_InitEntries[i].Name &&
269             !strcmp (AcpiGbl_InitEntries[i].Name, Pathname))
270         {
271             *ObjDesc = AcpiGbl_InitEntries[i].ObjDesc;
272             AcpiGbl_InitEntries[i].IsUsed = TRUE;
273             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Found match: %s, %p\n", Pathname, *ObjDesc));
274             return_ACPI_STATUS (AE_OK);
275         }
276     }
277 
278     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "No match found: %s\n", Pathname));
279     return_ACPI_STATUS (AE_NOT_FOUND);
280 }
281 
282 
283 /******************************************************************************
284  *
285  * FUNCTION:    AeDisplayUnusedInitFileItems
286  *
287  * PARAMETERS:  None
288  *
289  * RETURN:      None
290  *
291  * DESCRIPTION: Display all init file items that have not been referenced
292  *              (i.e., items that have not been found in the namespace).
293  *
294  *****************************************************************************/
295 
296 void
AeDisplayUnusedInitFileItems(void)297 AeDisplayUnusedInitFileItems (
298     void)
299 {
300     UINT32                  i;
301 
302 
303     if (!AcpiGbl_InitEntries)
304     {
305         return;
306     }
307 
308     for (i = 0; i < AcpiGbl_InitFileLineCount; ++i)
309     {
310         if (AcpiGbl_InitEntries[i].Name &&
311             !AcpiGbl_InitEntries[i].IsUsed)
312         {
313             AcpiOsPrintf ("Init file entry not found in namespace "
314                 "(or is a non-data type): %s\n",
315                 AcpiGbl_InitEntries[i].Name);
316         }
317     }
318 }
319 
320 
321 /******************************************************************************
322  *
323  * FUNCTION:    AeDeleteInitFileList
324  *
325  * PARAMETERS:  None
326  *
327  * RETURN:      None
328  *
329  * DESCRIPTION: Delete the global namespace initialization file data
330  *
331  *****************************************************************************/
332 
333 void
AeDeleteInitFileList(void)334 AeDeleteInitFileList (
335     void)
336 {
337     UINT32                  i;
338 
339 
340     if (!AcpiGbl_InitEntries)
341     {
342         return;
343     }
344 
345     for (i = 0; i < AcpiGbl_InitFileLineCount; ++i)
346     {
347 
348         if ((AcpiGbl_InitEntries[i].ObjDesc) && (AcpiGbl_InitEntries[i].Value))
349         {
350             /* Remove one reference on the object (and all subobjects) */
351 
352             AcpiUtRemoveReference (AcpiGbl_InitEntries[i].ObjDesc);
353         }
354     }
355 
356     AcpiOsFree (AcpiGbl_InitEntries);
357 }
358