efiacpi.c revision 1.5 1 /* $NetBSD: efiacpi.c,v 1.5 2019/11/30 13:02:18 jmcneill Exp $ */
2
3 /*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jared McNeill <jmcneill (at) invisible.ca>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "efiboot.h"
33 #include "efiacpi.h"
34 #include "efifdt.h"
35 #include "smbios.h"
36
37 #include <libfdt.h>
38
39 #define ACPI_FDT_SIZE (128 * 1024)
40
41 static EFI_GUID Acpi20TableGuid = ACPI_20_TABLE_GUID;
42 static EFI_GUID Smbios3TableGuid = SMBIOS3_TABLE_GUID;
43
44 static void *acpi_root = NULL;
45 static void *smbios3_table = NULL;
46
47 int
48 efi_acpi_probe(void)
49 {
50 EFI_STATUS status;
51
52 status = LibGetSystemConfigurationTable(&Acpi20TableGuid, &acpi_root);
53 if (EFI_ERROR(status))
54 return EIO;
55
56 status = LibGetSystemConfigurationTable(&Smbios3TableGuid, &smbios3_table);
57 if (EFI_ERROR(status))
58 smbios3_table = NULL;
59
60 return 0;
61 }
62
63 int
64 efi_acpi_available(void)
65 {
66 return acpi_root != NULL;
67 }
68
69 void
70 efi_acpi_show(void)
71 {
72 if (!efi_acpi_available())
73 return;
74
75 printf("ACPI: RSDP %p", acpi_root);
76 if (smbios3_table)
77 printf(", SMBIOS %p", smbios3_table);
78 printf("\n");
79 }
80
81 static char model_buf[128];
82
83 static const char *
84 efi_acpi_get_model(void)
85 {
86 struct smbtable smbios;
87 struct smbios_sys *psys;
88 const char *s;
89 char *buf;
90
91 memset(model_buf, 0, sizeof(model_buf));
92
93 if (smbios3_table != NULL) {
94 smbios_init(smbios3_table);
95
96 buf = model_buf;
97 smbios.cookie = 0;
98 if (smbios_find_table(SMBIOS_TYPE_SYSTEM, &smbios)) {
99 psys = smbios.tblhdr;
100 if ((s = smbios_get_string(&smbios, psys->vendor, buf, 64)) != NULL) {
101 buf += strlen(s);
102 *buf++ = ' ';
103 }
104 smbios_get_string(&smbios, psys->product, buf, 64);
105 }
106 }
107
108 if (model_buf[0] == '\0')
109 strcpy(model_buf, "ACPI");
110
111 return model_buf;
112 }
113
114 int
115 efi_acpi_create_fdt(void)
116 {
117 int error;
118 void *fdt;
119
120 if (acpi_root == NULL)
121 return EINVAL;
122
123 fdt = AllocatePool(ACPI_FDT_SIZE);
124 if (fdt == NULL)
125 return ENOMEM;
126
127 error = fdt_create_empty_tree(fdt, ACPI_FDT_SIZE);
128 if (error)
129 return EIO;
130
131 const char *model = efi_acpi_get_model();
132
133 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "compatible", "netbsd,generic-acpi");
134 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", model);
135 fdt_setprop_cell(fdt, fdt_path_offset(fdt, "/"), "#address-cells", 2);
136 fdt_setprop_cell(fdt, fdt_path_offset(fdt, "/"), "#size-cells", 2);
137
138 fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), "chosen");
139 fdt_setprop_u64(fdt, fdt_path_offset(fdt, "/chosen"), "netbsd,acpi-root-table", (uint64_t)(uintptr_t)acpi_root);
140 if (smbios3_table)
141 fdt_setprop_u64(fdt, fdt_path_offset(fdt, "/chosen"), "netbsd,smbios-table", (uint64_t)(uintptr_t)smbios3_table);
142 #ifdef EFIBOOT_RUNTIME_ADDRESS
143 fdt_setprop_u64(fdt, fdt_path_offset(fdt, "/chosen"), "netbsd,uefi-system-table", (uint64_t)(uintptr_t)ST);
144 #endif
145
146 fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), "acpi");
147 fdt_setprop_string(fdt, fdt_path_offset(fdt, "/acpi"), "compatible", "netbsd,acpi");
148
149 return efi_fdt_set_data(fdt);
150 }
151