MOS Source Code
Loading...
Searching...
No Matches
acpi.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
5#include "mos/mm/mm.h"
9
10#include <mos/mos_global.h>
11#include <mos/syslog/printk.h>
12#include <mos/x86/acpi/acpi.h>
13#include <mos/x86/acpi/madt.h>
14#include <mos/x86/cpu/cpu.h>
18#include <mos_stdlib.h>
19#include <mos_string.h>
20#include <stddef.h>
21
23
25 0,
26};
27
29
30#define do_verify_checksum(var, header, type) \
31 var = container_of(header, type, sdt_header); \
32 if (!verify_sdt_checksum(&(var)->sdt_header)) \
33 mos_panic(#type " checksum error");
34
41
42static bool acpi_sysfs_mmap(sysfs_file_t *f, vmap_t *vmap, off_t offset)
43{
45 const ssize_t item_npages = ALIGN_UP_TO_PAGE(item->size) / MOS_PAGE_SIZE;
46 if (offset >= item_npages)
47 return false;
48
49 const size_t npages = MIN((ssize_t) vmap->npages, item_npages - offset); // limit to the number of pages in the item
50 mm_do_map(vmap->mmctx->pgd, vmap->vaddr, phyframe_pfn(item->pages), npages, vmap->vmflags, false); // no need to refcount
51 return true;
52}
53
54static bool acpi_sysfs_munmap(sysfs_file_t *f, vmap_t *vmap, bool *unmapped)
55{
56 MOS_UNUSED(f);
57 mm_do_unmap(vmap->mmctx->pgd, vmap->vaddr, vmap->npages, false);
58 *unmapped = true;
59 return true;
60}
61
62static void register_sysfs_acpi_rsdp(const acpi_rsdp_t *rsdp)
63{
64 acpi_sysfs_item_t *const item = kmalloc(sizeof(acpi_sysfs_item_t));
65 item->size = rsdp->length;
66 item->item.name = strndup("RSDP", 4);
69 item->item.mem.size = item->size;
70 item->item.type = SYSFS_MEM;
72 if (!item->pages)
73 mos_panic("failed to allocate pages for ACPI table");
74
75 memcpy((void *) phyframe_va(item->pages), rsdp, rsdp->length);
76 pmm_ref(item->pages, true); // don't free the pages when the item is freed
77
79}
80
81static void register_sysfs_acpi_node(const char table_name[4], const acpi_sdt_header_t *header)
82{
83 acpi_sysfs_item_t *const item = kmalloc(sizeof(acpi_sysfs_item_t));
84 item->size = header->length;
85 item->item.name = strndup(table_name, 4);
88 item->item.mem.size = item->size;
89 item->item.type = SYSFS_MEM;
91 if (!item->pages)
92 mos_panic("failed to allocate pages for ACPI table");
93
94 memcpy((void *) phyframe_va(item->pages), header, header->length);
95 pmm_ref(item->pages, true); // don't free the pages when the item is freed
96
98}
99
101{
102 u8 sum = 0;
103 for (u32 i = 0; i < tableHeader->length; i++)
104 sum += ((char *) tableHeader)[i];
105 return sum == 0;
106}
107
108static void do_handle_sdt_header(const acpi_sdt_header_t *const header)
109{
110 register_sysfs_acpi_node(header->signature, header);
111 pr_dinfo2(x86_acpi, "%.4s at %p, size %u", header->signature, (void *) header, header->length);
112
113 if (strncmp(header->signature, ACPI_SIGNATURE_FADT, 4) == 0)
114 {
115 const acpi_fadt_t *x86_acpi_fadt;
116 do_verify_checksum(x86_acpi_fadt, header, acpi_fadt_t);
117
118 const acpi_sdt_header_t *const dsdt = (acpi_sdt_header_t *) pa_va(x86_acpi_fadt->dsdt);
119 if (!verify_sdt_checksum(dsdt))
120 mos_panic("DSDT checksum error");
121 pr_dinfo2(x86_acpi, "DSDT at %p, size %u", (void *) dsdt, dsdt->length);
122 x86_acpi_dsdt = (ptr_t) dsdt;
123 register_sysfs_acpi_node("DSDT", dsdt);
124 }
125 else if (strncmp(header->signature, ACPI_SIGNATURE_MADT, 4) == 0)
126 {
128 }
129}
130
131static void do_iterate_sdts(const acpi_rsdp_t *rsdp)
132{
133 if (rsdp->v1.revision == 0)
134 {
135 const acpi_sdt_header_t *rsdt_header = (acpi_sdt_header_t *) pa_va(rsdp->v1.rsdt_addr);
136 if (strncmp(rsdt_header->signature, "RSDT", 4) != 0)
137 mos_panic("RSDT signature mismatch");
138
139 const acpi_rsdt_t *x86_acpi_rsdt;
140 do_verify_checksum(x86_acpi_rsdt, rsdt_header, acpi_rsdt_t);
141
142 const size_t num_headers = (x86_acpi_rsdt->sdt_header.length - sizeof(acpi_sdt_header_t)) / sizeof(ptr32_t);
143 for (size_t i = 0; i < num_headers; i++)
144 {
145 const acpi_sdt_header_t *const header = (acpi_sdt_header_t *) pa_va(x86_acpi_rsdt->sdts[i]);
146 do_handle_sdt_header(header);
147 }
148 }
149 else if (rsdp->v1.revision == 2)
150 {
151 const acpi_sdt_header_t *xsdt_header = (acpi_sdt_header_t *) pa_va(rsdp->xsdt_addr);
152 if (strncmp(xsdt_header->signature, "XSDT", 4) != 0)
153 mos_panic("XSDT signature mismatch");
154
155 MOS_ASSERT_X(verify_sdt_checksum(xsdt_header), "acpi_xsdt_t checksum error");
156
157 const acpi_xsdt_t *x86_acpi_xsdt;
158 x86_acpi_xsdt = container_of(xsdt_header, acpi_xsdt_t, sdt_header);
159
160 const size_t num_headers = (x86_acpi_xsdt->sdt_header.length - sizeof(acpi_sdt_header_t)) / sizeof(ptr64_t);
161 for (size_t i = 0; i < num_headers; i++)
162 {
163 const acpi_sdt_header_t *const header = (acpi_sdt_header_t *) pa_va(x86_acpi_xsdt->sdts[i]);
164 do_handle_sdt_header(header);
165 }
166 }
167 else
168 {
169 mos_panic("ACPI: RSDP revision %d not supported", rsdp->v1.revision);
170 }
171}
172
174{
175 pr_dinfo2(x86_acpi, "initializing ACPI with RSDP at %p", (void *) rsdp);
177 do_iterate_sdts(rsdp);
178}
179
181{
182 for (ptr_t addr = start; addr < start + size; addr += 0x10)
183 {
184 if (strncmp((const char *) addr, ACPI_SIGNATURE_RSDP, 8) == 0)
185 {
186 pr_dinfo2(x86_acpi, "ACPI: RSDP magic at %p", (void *) addr);
187 acpi_rsdp_t *rsdp = (acpi_rsdp_t *) addr;
188
189 // check the checksum
190 u8 sum = 0;
191 for (u32 i = 0; i < sizeof(acpi_rsdp_v1_t); i++)
192 sum += ((u8 *) rsdp)[i];
193
194 if (sum != 0)
195 {
196 pr_info2("ACPI: RSDP checksum failed");
197 continue;
198 }
199 pr_dinfo2(x86_acpi, "ACPI: oem: '%.6s', revision: %d", rsdp->v1.oem_id, rsdp->v1.revision);
200
201 if (rsdp->v1.revision != 0 && rsdp->v1.revision != 2)
202 mos_panic("ACPI: RSDP revision %d not supported", rsdp->v1.revision);
203
204 return rsdp;
205 }
206 }
207 return NULL;
208}
static bool acpi_sysfs_munmap(sysfs_file_t *f, vmap_t *vmap, bool *unmapped)
Definition acpi.c:54
static sysfs_dir_t __sysfs_acpi
Definition acpi.c:28
static void register_sysfs_acpi_node(const char table_name[4], const acpi_sdt_header_t *header)
Definition acpi.c:81
#define do_verify_checksum(var, header, type)
Definition acpi.c:30
static void do_iterate_sdts(const acpi_rsdp_t *rsdp)
Definition acpi.c:131
void acpi_parse_rsdt(const acpi_rsdp_t *rsdp)
Definition acpi.c:173
static sysfs_item_t acpi_sysfs_items[]
Definition acpi.c:24
should_inline bool verify_sdt_checksum(const acpi_sdt_header_t *tableHeader)
Definition acpi.c:100
static void do_handle_sdt_header(const acpi_sdt_header_t *const header)
Definition acpi.c:108
static void register_sysfs_acpi_rsdp(const acpi_rsdp_t *rsdp)
Definition acpi.c:62
ptr_t x86_acpi_dsdt
Definition acpi.c:22
static bool acpi_sysfs_mmap(sysfs_file_t *f, vmap_t *vmap, off_t offset)
Definition acpi.c:42
const acpi_rsdp_t * acpi_find_rsdp(ptr_t start, size_t size)
Definition acpi.c:180
#define ACPI_SIGNATURE_RSDP
Definition acpi_types.h:29
#define ACPI_SIGNATURE_MADT
Definition acpi_types.h:217
#define ACPI_SIGNATURE_FADT
Definition acpi_types.h:136
#define MOS_ASSERT_X(cond, msg,...)
Definition assert.h:15
#define MOS_PAGE_SIZE
Definition autoconf.h:6
MOSAPI s32 strncmp(const char *str1, const char *str2, size_t n)
Definition mos_string.c:32
MOSAPI char * strndup(const char *src, size_t n)
#define MIN(a, b)
Definition mos_stdlib.h:30
#define phyframe_va(frame)
Definition mm.h:79
#define pa_va(pa)
Definition mm.h:80
phyframe_t * mm_get_free_pages(size_t npages)
Definition mm.c:55
#define pmm_ref(thing, npages)
Definition pmm.h:143
#define phyframe_pfn(frame)
Definition pmm.h:80
const acpi_madt_t * x86_acpi_madt
Definition madt.c:11
#define should_inline
Definition mos_global.h:37
#define ALIGN_UP_TO_PAGE(addr)
Definition mos_global.h:75
#define MOS_UNUSED(x)
Definition mos_global.h:64
#define container_of(ptr, type, member)
Definition mos_global.h:50
#define mos_panic(fmt,...)
Definition panic.h:55
static void * memcpy(void *s1, const void *s2, size_t n)
Definition pb_syshdr.h:90
#define NULL
Definition pb_syshdr.h:46
#define pr_info2(fmt,...)
Definition printk.h:36
#define pr_dinfo2(feat, fmt,...)
Definition printk.h:27
size_t size
Definition slab.c:30
char oem_id[6]
Definition acpi_types.h:11
acpi_rsdp_v1_t v1
Definition acpi_types.h:20
ptr32_t sdts[]
Definition acpi_types.h:48
acpi_sdt_header_t sdt_header
Definition acpi_types.h:47
sysfs_item_t item
Definition acpi.c:37
size_t size
Definition acpi.c:38
phyframe_t * pages
Definition acpi.c:39
ptr64_t sdts[]
Definition acpi_types.h:54
acpi_sdt_header_t sdt_header
Definition acpi_types.h:53
pgd_t pgd
Definition platform.h:82
sysfs_item_type_t type
Definition sysfs.h:23
bool(* mmap)(sysfs_file_t *file, vmap_t *vmap, off_t offset)
Definition sysfs.h:32
size_t size
Definition sysfs.h:34
const char * name
Definition sysfs.h:22
bool(* munmap)(sysfs_file_t *file, vmap_t *vmap, bool *unmapped)
Definition sysfs.h:33
struct sysfs_item_t::@8::@10 mem
Definition mm.h:58
ptr_t vaddr
Definition mm.h:62
size_t npages
Definition mm.h:63
vm_flags vmflags
Definition mm.h:64
mm_context_t * mmctx
Definition mm.h:65
void sysfs_register_file(sysfs_dir_t *sysfs_dir, sysfs_item_t *item)
Register an entry in a sysfs directory.
Definition sysfs.c:383
sysfs_item_t * sysfs_file_get_item(sysfs_file_t *file)
Definition sysfs.c:115
@ SYSFS_MEM
memory-backed file
Definition sysfs.h:16
#define SYSFS_AUTOREGISTER(sysfs_name, sysfs_items)
void mm_do_map(pgd_t top, ptr_t vaddr, pfn_t pfn, size_t n_pages, vm_flags flags, bool do_refcount)
Definition table_ops.c:23
void mm_do_unmap(pgd_t top, ptr_t vaddr, size_t n_pages, bool do_unref)
Definition table_ops.c:35
unsigned int u32
Definition types.h:21
ssize_t off_t
Definition types.h:84
unsigned int ptr32_t
Definition types.h:26
unsigned long ptr_t
Definition types.h:25
unsigned long long ptr64_t
Definition types.h:27
signed long ssize_t
Definition types.h:83
unsigned char u8
Definition types.h:19