diff --git a/include/uacpi/internal/io.h b/include/uacpi/internal/io.h index 4c875d88..d9153db9 100644 --- a/include/uacpi/internal/io.h +++ b/include/uacpi/internal/io.h @@ -19,3 +19,13 @@ uacpi_status uacpi_read_field_unit( uacpi_status uacpi_write_field_unit( uacpi_field_unit *field, const void *src, uacpi_size size ); + +uacpi_status uacpi_system_io_read( + uacpi_io_addr address, uacpi_u8 width, uacpi_u64 *out +); +uacpi_status uacpi_system_io_write( + uacpi_io_addr address, uacpi_u8 width, uacpi_u64 in +); + +uacpi_status uacpi_system_memory_read(void *ptr, uacpi_u8 width, uacpi_u64 *out); +uacpi_status uacpi_system_memory_write(void *ptr, uacpi_u8 width, uacpi_u64 in); diff --git a/include/uacpi/kernel_api.h b/include/uacpi/kernel_api.h index a8240775..9f6acf95 100644 --- a/include/uacpi/kernel_api.h +++ b/include/uacpi/kernel_api.h @@ -30,38 +30,6 @@ void uacpi_kernel_deinitialize(void); // Returns the PHYSICAL address of the RSDP structure via *out_rsdp_address. uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out_rsdp_address); -/* - * Raw IO API, this is only used for accessing verified data from - * "safe" code (aka not indirectly invoked by the AML interpreter), - * e.g. programming FADT & FACS registers. - * - * NOTE: - * 'byte_width' is ALWAYS one of 1, 2, 4, 8. You are NOT allowed to implement - * this in terms of memcpy, as hardware expects accesses to be of the EXACT - * width. - * ------------------------------------------------------------------------- - */ -uacpi_status uacpi_kernel_raw_memory_read( - uacpi_phys_addr address, uacpi_u8 byte_width, uacpi_u64 *out_value -); -uacpi_status uacpi_kernel_raw_memory_write( - uacpi_phys_addr address, uacpi_u8 byte_width, uacpi_u64 in_value -); - -/* - * NOTE: - * 'byte_width' is ALWAYS one of 1, 2, 4. You are NOT allowed to break e.g. a - * 4-byte access into four 1-byte accesses. Hardware ALWAYS expects accesses to - * be of the exact width. - */ -uacpi_status uacpi_kernel_raw_io_read( - uacpi_io_addr address, uacpi_u8 byte_width, uacpi_u64 *out_value -); -uacpi_status uacpi_kernel_raw_io_write( - uacpi_io_addr address, uacpi_u8 byte_width, uacpi_u64 in_value -); -// ------------------------------------------------------------------------- - /* * NOTE: * 'byte_width' is ALWAYS one of 1, 2, 4. Since PCI registers are 32 bits wide diff --git a/source/default_handlers.c b/source/default_handlers.c index e21762ba..cb569a04 100644 --- a/source/default_handlers.c +++ b/source/default_handlers.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -262,50 +263,6 @@ static uacpi_status io_region_detach(uacpi_region_detach_data *data) return UACPI_STATUS_OK; } -static uacpi_status memory_read(void *ptr, uacpi_u8 width, uacpi_u64 *out) -{ - switch (width) { - case 1: - *out = *(volatile uacpi_u8*)ptr; - break; - case 2: - *out = *(volatile uacpi_u16*)ptr; - break; - case 4: - *out = *(volatile uacpi_u32*)ptr; - break; - case 8: - *out = *(volatile uacpi_u64*)ptr; - break; - default: - return UACPI_STATUS_INVALID_ARGUMENT; - } - - return UACPI_STATUS_OK; -} - -static uacpi_status memory_write(void *ptr, uacpi_u8 width, uacpi_u64 in) -{ - switch (width) { - case 1: - *(volatile uacpi_u8*)ptr = in; - break; - case 2: - *(volatile uacpi_u16*)ptr = in; - break; - case 4: - *(volatile uacpi_u32*)ptr = in; - break; - case 8: - *(volatile uacpi_u64*)ptr = in; - break; - default: - return UACPI_STATUS_INVALID_ARGUMENT; - } - - return UACPI_STATUS_OK; -} - static uacpi_status memory_region_do_rw( uacpi_region_op op, uacpi_region_rw_data *data ) @@ -316,8 +273,8 @@ static uacpi_status memory_region_do_rw( ptr = ctx->virt + (data->address - ctx->phys); return op == UACPI_REGION_OP_READ ? - memory_read(ptr, data->byte_width, &data->value) : - memory_write(ptr, data->byte_width, data->value); + uacpi_system_memory_read(ptr, data->byte_width, &data->value) : + uacpi_system_memory_write(ptr, data->byte_width, data->value); } static uacpi_status handle_memory_region(uacpi_region_op op, uacpi_handle op_data) @@ -342,8 +299,8 @@ static uacpi_status table_data_region_do_rw( void *addr = UACPI_VIRT_ADDR_TO_PTR((uacpi_virt_addr)data->offset); return op == UACPI_REGION_OP_READ ? - memory_read(addr, data->byte_width, &data->value) : - memory_write(addr, data->byte_width, data->value); + uacpi_system_memory_read(addr, data->byte_width, &data->value) : + uacpi_system_memory_write(addr, data->byte_width, data->value); } static uacpi_status handle_table_data_region(uacpi_region_op op, uacpi_handle op_data) diff --git a/source/io.c b/source/io.c index 7245b137..cc35844f 100644 --- a/source/io.c +++ b/source/io.c @@ -517,13 +517,16 @@ uacpi_status uacpi_gas_read(const struct acpi_gas *gas, uacpi_u64 *out_value) uacpi_u64 address = gas->address + (index * access_byte_width); if (gas->address_space_id == UACPI_ADDRESS_SPACE_SYSTEM_IO) { - ret = uacpi_kernel_raw_io_read( - address, access_byte_width, &data - ); + ret = uacpi_system_io_read(address, access_byte_width, &data); } else { - ret = uacpi_kernel_raw_memory_read( - address, access_byte_width, &data - ); + void *virt; + + virt = uacpi_kernel_map(address, access_byte_width); + if (uacpi_unlikely(virt == UACPI_NULL)) + return UACPI_STATUS_MAPPING_FAILED; + + ret = uacpi_system_memory_read(virt, access_byte_width, &data); + uacpi_kernel_unmap(virt, access_bit_width); } if (uacpi_unlikely_error(ret)) return ret; @@ -564,13 +567,16 @@ uacpi_status uacpi_gas_write(const struct acpi_gas *gas, uacpi_u64 in_value) uacpi_u64 address = gas->address + (index * access_byte_width); if (gas->address_space_id == UACPI_ADDRESS_SPACE_SYSTEM_IO) { - ret = uacpi_kernel_raw_io_write( - address, access_byte_width, data - ); + ret = uacpi_system_io_write(address, access_byte_width, data); } else { - ret = uacpi_kernel_raw_memory_write( - address, access_byte_width, data - ); + void *virt; + + virt = uacpi_kernel_map(address, access_byte_width); + if (uacpi_unlikely(virt == UACPI_NULL)) + return UACPI_STATUS_MAPPING_FAILED; + + ret = uacpi_system_memory_write(virt, access_byte_width, data); + uacpi_kernel_unmap(virt, access_bit_width); } if (uacpi_unlikely_error(ret)) return ret; @@ -582,3 +588,81 @@ uacpi_status uacpi_gas_write(const struct acpi_gas *gas, uacpi_u64 in_value) return UACPI_STATUS_OK; } + +uacpi_status uacpi_system_io_read( + uacpi_io_addr address, uacpi_u8 width, uacpi_u64 *out +) +{ + uacpi_status ret; + uacpi_handle handle; + + ret = uacpi_kernel_io_map(address, width, &handle); + if (uacpi_unlikely_error(ret)) + return ret; + + ret = uacpi_kernel_io_read(handle, 0, width, out); + uacpi_kernel_io_unmap(handle); + + return ret; +} + +uacpi_status uacpi_system_io_write( + uacpi_io_addr address, uacpi_u8 width, uacpi_u64 in +) +{ + uacpi_status ret; + uacpi_handle handle; + + ret = uacpi_kernel_io_map(address, width, &handle); + if (uacpi_unlikely_error(ret)) + return ret; + + ret = uacpi_kernel_io_write(handle, 0, width, in); + uacpi_kernel_io_unmap(handle); + + return ret; +} + +uacpi_status uacpi_system_memory_read(void *ptr, uacpi_u8 width, uacpi_u64 *out) +{ + switch (width) { + case 1: + *out = *(volatile uacpi_u8*)ptr; + break; + case 2: + *out = *(volatile uacpi_u16*)ptr; + break; + case 4: + *out = *(volatile uacpi_u32*)ptr; + break; + case 8: + *out = *(volatile uacpi_u64*)ptr; + break; + default: + return UACPI_STATUS_INVALID_ARGUMENT; + } + + return UACPI_STATUS_OK; +} + +uacpi_status uacpi_system_memory_write(void *ptr, uacpi_u8 width, uacpi_u64 in) +{ + switch (width) { + case 1: + *(volatile uacpi_u8*)ptr = in; + break; + case 2: + *(volatile uacpi_u16*)ptr = in; + break; + case 4: + *(volatile uacpi_u32*)ptr = in; + break; + case 8: + *(volatile uacpi_u64*)ptr = in; + break; + default: + return UACPI_STATUS_INVALID_ARGUMENT; + } + + return UACPI_STATUS_OK; +} diff --git a/source/registers.c b/source/registers.c index 234e7590..1efe2800 100644 --- a/source/registers.c +++ b/source/registers.c @@ -106,7 +106,7 @@ static uacpi_status read_one( return uacpi_gas_read(reg, out_value); } - return uacpi_kernel_raw_io_read(*(uacpi_u32*)reg, byte_width, out_value); + return uacpi_system_io_read(*(uacpi_u32*)reg, byte_width, out_value); } static uacpi_status write_one( @@ -123,7 +123,7 @@ static uacpi_status write_one( return uacpi_gas_write(reg, in_value); } - return uacpi_kernel_raw_io_write(*(uacpi_u32*)reg, byte_width, in_value); + return uacpi_system_io_write(*(uacpi_u32*)reg, byte_width, in_value); } static uacpi_status do_read_register( diff --git a/source/sleep.c b/source/sleep.c index d6e45166..1148c099 100644 --- a/source/sleep.c +++ b/source/sleep.c @@ -550,9 +550,7 @@ uacpi_status uacpi_reboot(void) * For SystemIO we don't do any checking, and we ignore bit width * because that's what NT does. */ - ret = uacpi_kernel_raw_io_write( - reset_reg->address, 1, fadt->reset_value - ); + ret = uacpi_system_io_write(reset_reg->address, 1, fadt->reset_value); break; case UACPI_ADDRESS_SPACE_SYSTEM_MEMORY: ret = uacpi_write_register(UACPI_REGISTER_RESET, fadt->reset_value); diff --git a/tests/runner/interface_impl.cpp b/tests/runner/interface_impl.cpp index badd291a..c853aea1 100644 --- a/tests/runner/interface_impl.cpp +++ b/tests/runner/interface_impl.cpp @@ -53,45 +53,6 @@ void uacpi_kernel_deinitialize(void) } #endif -uacpi_status uacpi_kernel_raw_memory_read( - uacpi_phys_addr, uacpi_u8, uacpi_u64 *ret -) -{ - *ret = 0; - return UACPI_STATUS_OK; -} - -uacpi_status uacpi_kernel_raw_memory_write( - uacpi_phys_addr, uacpi_u8, uacpi_u64 -) -{ - return UACPI_STATUS_OK; -} - -uacpi_status uacpi_kernel_raw_io_read( - uacpi_io_addr addr, uacpi_u8 width, uacpi_u64 *ret -) -{ - if (io_space && addr <= UINT16_MAX) { - *ret = 0; - memcpy(ret, &io_space[addr], width); - } else { - *ret = 0xFFFFFFFFFFFFFFFF; - } - - return UACPI_STATUS_OK; -} - -uacpi_status uacpi_kernel_raw_io_write( - uacpi_io_addr addr, uacpi_u8 width, uacpi_u64 value -) -{ - if (io_space && addr <= UINT16_MAX) - memcpy(&io_space[addr], &value, width); - - return UACPI_STATUS_OK; -} - uacpi_status uacpi_kernel_io_map(uacpi_io_addr addr, uacpi_size, uacpi_handle *out_handle) { @@ -106,9 +67,16 @@ uacpi_status uacpi_kernel_io_read( uacpi_u8 byte_width, uacpi_u64 *value ) { - return uacpi_kernel_raw_io_read( - (uacpi_io_addr)handle + offset, byte_width, value - ); + auto addr = (uacpi_io_addr)handle + offset; + + if (io_space && addr <= UINT16_MAX) { + *value = 0; + memcpy(value, &io_space[addr], byte_width); + } else { + *value = 0xFFFFFFFFFFFFFFFF; + } + + return UACPI_STATUS_OK; } uacpi_status uacpi_kernel_pci_read( @@ -124,16 +92,19 @@ uacpi_status uacpi_kernel_io_write( uacpi_u8 byte_width, uacpi_u64 value ) { - return uacpi_kernel_raw_io_write( - (uacpi_io_addr)handle + offset, byte_width, value - ); + auto addr = (uacpi_io_addr)handle + offset; + + if (io_space && addr <= UINT16_MAX) + memcpy(&io_space[addr], &value, byte_width); + + return UACPI_STATUS_OK; } uacpi_status uacpi_kernel_pci_write( - uacpi_pci_address*, uacpi_size, uacpi_u8, uacpi_u64 + uacpi_pci_address*, uacpi_size offset, uacpi_u8 byte_width, uacpi_u64 value ) { - return UACPI_STATUS_OK; + return uacpi_kernel_io_write(nullptr, offset, byte_width, value); } bool g_expect_virtual_addresses = true;