1 /* 2 * Copyright 2022, Jérôme Duval. All rights reserved. 3 * 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <string.h> 11 12 #include <Drivers.h> 13 #include <KernelExport.h> 14 #include <OS.h> 15 16 #include "ACPIPrivate.h" 17 18 19 #define TRACE(x...) //dprintf("acpi_call: " x) 20 #define TRACE_ALWAYS(x...) dprintf("acpi_call: " x) 21 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 22 23 24 typedef struct { 25 device_node *node; 26 acpi_root_info *acpi; 27 void *acpi_cookie; 28 } acpi_call_device_info; 29 30 31 struct acpi_call_desc 32 { 33 char* path; 34 acpi_objects args; 35 acpi_status retval; 36 acpi_data result; 37 acpi_size reslen; 38 }; 39 40 41 // #pragma mark - device module API 42 43 44 static status_t 45 acpi_call_init_device(void* _node, void** _cookie) 46 { 47 CALLED(); 48 device_node *node = (device_node *)_node; 49 50 acpi_call_device_info* device = (acpi_call_device_info*)calloc(1, sizeof(acpi_call_device_info)); 51 if (device == NULL) 52 return B_NO_MEMORY; 53 54 device->node = node; 55 status_t err = gDeviceManager->get_driver(node, (driver_module_info **)&device->acpi, 56 (void **)&device->acpi_cookie); 57 if (err != B_OK) { 58 free(device); 59 return err; 60 } 61 62 *_cookie = device; 63 return err; 64 } 65 66 67 static void 68 acpi_call_uninit_device(void* _cookie) 69 { 70 CALLED(); 71 acpi_call_device_info* device = (acpi_call_device_info*)_cookie; 72 free(device); 73 } 74 75 76 static status_t 77 acpi_call_open(void* _device, const char* path, int openMode, void** _cookie) 78 { 79 CALLED(); 80 acpi_call_device_info* device = (acpi_call_device_info*)_device; 81 82 *_cookie = device; 83 return B_OK; 84 } 85 86 87 static status_t 88 acpi_call_read(void *cookie, off_t position, void *buffer, size_t *numBytes) 89 { 90 TRACE("read(%p, %" B_PRIdOFF", %p, %lu)\n", cookie, position, buffer, *numBytes); 91 return B_ERROR; 92 } 93 94 95 static status_t 96 acpi_call_write(void *cookie, off_t position, const void *buffer, 97 size_t *numBytes) 98 { 99 TRACE("write(%p, %" B_PRIdOFF", %p, %lu)\n", cookie, position, buffer, *numBytes); 100 return B_ERROR; 101 } 102 103 104 void 105 acpi_call_fixup_pointers(acpi_object_type *p, void *target) 106 { 107 CALLED(); 108 switch (p->object_type) 109 { 110 case ACPI_TYPE_STRING: 111 p->string.string = (char*)((uint8*)(p->string.string) - (uint8*)p + (uint8*)target); 112 break; 113 case ACPI_TYPE_BUFFER: 114 p->buffer.buffer = (void*)((uint8*)(p->buffer.buffer) - (uint8*)p + (uint8*)target); 115 break; 116 } 117 } 118 119 120 static status_t 121 acpi_call_control(void *_device, uint32 op, void *buffer, size_t length) 122 { 123 TRACE("control(%p, %" B_PRIu32 ", %p, %lu)\n", _device, op, buffer, length); 124 acpi_call_device_info* device = (acpi_call_device_info*)_device; 125 126 if (op == 'ACCA') { 127 struct acpi_call_desc params; 128 char path[1024]; 129 if (user_memcpy(¶ms, buffer, sizeof(params)) != B_OK 130 || user_memcpy(path, params.path, sizeof(path)) != B_OK) { 131 return B_BAD_ADDRESS; 132 } 133 acpi_data result; 134 result.length = ACPI_ALLOCATE_BUFFER; 135 result.pointer = NULL; 136 137 acpi_status retval = device->acpi->evaluate_method(NULL, path, ¶ms.args, &result); 138 if (retval == 0) { 139 if (result.pointer != NULL) { 140 if (params.result.pointer != NULL) { 141 params.result.length = min_c(params.result.length, result.length); 142 if (result.length >= sizeof(acpi_object_type)) 143 acpi_call_fixup_pointers((acpi_object_type*)(result.pointer), params.result.pointer); 144 145 if (user_memcpy(params.result.pointer, result.pointer, params.result.length) != B_OK 146 || user_memcpy(buffer, ¶ms, sizeof(params)) != B_OK) { 147 return B_BAD_ADDRESS; 148 } 149 } 150 free(result.pointer); 151 } 152 } 153 return B_OK; 154 } 155 156 return B_ERROR; 157 } 158 159 160 static status_t 161 acpi_call_close(void *cookie) 162 { 163 TRACE("close(%p)\n", cookie); 164 return B_OK; 165 } 166 167 168 static status_t 169 acpi_call_free(void *cookie) 170 { 171 TRACE("free(%p)\n", cookie); 172 return B_OK; 173 } 174 175 176 // #pragma mark - 177 178 179 struct device_module_info gAcpiCallDeviceModule = { 180 { 181 ACPI_CALL_DEVICE_MODULE_NAME, 182 0, 183 NULL 184 }, 185 186 acpi_call_init_device, 187 acpi_call_uninit_device, 188 NULL, // remove, 189 190 acpi_call_open, 191 acpi_call_close, 192 acpi_call_free, 193 acpi_call_read, 194 acpi_call_write, 195 NULL, // io 196 acpi_call_control, 197 198 NULL, // select 199 NULL, // deselect 200 }; 201 202