diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index 1e0321412..c20496cfc 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -700,7 +700,109 @@ DECLARE_XBOXKRNL_EXPORT1(NtDeviceIoControlFile, kFileSystem, kStub); // ObCreateObject // todo: need device guest object struct + host object for device -dword_result_t IoCreateDevice_entry(dword_t driver_object, +struct X_DRIVER_OBJECT { + xe::be driver_start_io_ptr; + xe::be driver_delete_device_ptr; + xe::be driver_dismount_volume_ptr; + xe::be major_function_ptr[11]; +}; +static_assert_size(X_DRIVER_OBJECT, 0x38); + +struct X_KDEVICE_QUEUE { + xe::be type; // 0x0 sz:0x2 + xe::be padding; // 0x2 sz:0x1 + xe::be busy; // 0x3 sz:0x1 + xe::be lock; // 0x4 sz:0x4 + xe::be device_list_head; // 0x8 sz:0x8 +}; +static_assert_size(X_KDEVICE_QUEUE, 0x10); + +struct X_KDEVICE_QUEUE_ENTRY { + X_LIST_ENTRY device_list_entry; // 0x0 sz:0x2 + xe::be sort_key; // 0x8 sz:0x4 + xe::be inserted; // 0xC sz:0x1 +}; +static_assert_size(X_KDEVICE_QUEUE_ENTRY, 0x10); + +struct X_IRP_ASYNC_PARAM { + xe::be user_apc_routine_ptr; // 0x0 sz:0x4 + xe::be user_apc_context_ptr; // 0x4 sz:0x4 +}; +static_assert_size(X_IRP_ASYNC_PARAM, 0x8); + +union X_UNION_IRP_OVERLAY { + X_IRP_ASYNC_PARAM asynchronous_parameters; + xe::be allocation_size; +}; + +struct X_IRP_OVERLAY { + union { + X_KDEVICE_QUEUE_ENTRY device_queue_entry; // 0x0 sz:0x10 + X_LIST_ENTRY device_list_entry; // 0x0 sz:0x8 + xe::be driver_context_ptr[4]; // 0x0 sz:0x10 + }; + xe::be locked_buffer_length; // 0x10 sz:0x4 + xe::be thread_ptr; // 0x14 sz:0x4 + X_LIST_ENTRY list_entry; // 0x18 sz:0x8 + union { + xe::be + current_stack_location_ptr; // 0x20 sz:0x4, X_IO_STACK_LOCATION -> 0x24 + xe::be packet_type; // 0x20 sz:0x4 + }; + xe::be + original_file_object_ptr; // 0x24 sz:0x4, X_FILE_OBJECT -> 0x68 +}; +static_assert_size(X_IRP_OVERLAY, 0x28); + +union X_IRP_TAIL { + X_IRP_OVERLAY overlay; // 0x0 sz:0x28 + xe::be apc; // 0x0 sz:0x28 + xe::be completion_key_ptr; // 0x0 sz:0x4 +}; + +struct X_IRP { + xe::be type; // 0x0 sz:0x2 + xe::be size; // 0x2 sz:0x2 + xe::be flags; // 0x4 sz:0x4 + X_LIST_ENTRY thread_list_entry; // 0x8 sz:0x8 + X_IO_STATUS_BLOCK io_status; // 0x10 sz:0x8 + xe::be stack_count; // 0x18 sz:0x1 + xe::be current_location; // 0x19 sz:0x1 + xe::be pending_returned; // 0x1A sz:0x1 + xe::be cancel; // 0x1B sz:0x1 + xe::be user_buffer_ptr; // 0x1C sz:0x4 + xe::be user_iosb_ptr; // 0x20 sz:0x4, X_IO_STATUS_BLOCK* + xe::be user_event_ptr; // 0x24 sz:0x4, X_KEVENT* + X_UNION_IRP_OVERLAY overlay; // 0x28 sz:0x8 + X_IRP_TAIL tail; // 0x30 sz:0x28 + xe::be cancel_routine_ptr; // 0x58 sz:0x4 +}; +static_assert_size(X_IRP, 0x60); + +struct X_DEVICE_OBJECT { + xe::be type; // 0x0 sz:0x2 + xe::be device_extension_size; // 0x2 sz:0x2 + xe::be reference_count; // 0x4 sz:0x4 + xe::be drive_object_ptr; // 0x8 sz:0x4, X_DRIVER_OBJECT* + xe::be mounted_or_self_device; // 0xC sz:0x4, X_DEVICE_OBJECT* + xe::be current_irp_ptr; // 0x10 sz:0x4, X_IRP* + xe::be flags; // 0x14 sz:0x4 + xe::be device_extension_ptr; // 0x18 sz:0x4 + xe::be device_type; // 0x1C sz:0x1 + xe::be start_io_flags; // 0x1D sz:0x1 + xe::be stack_size; // 0x1E sz:0x1 + xe::be delete_pending; // 0x1F sz:0x1 + xe::be sector_size; // 0x20 sz:0x4, set by XamRamDriveCreate + xe::be + alignment; // 0x24 sz:0x4, NtQueryInformationFile called to verify + xe::be device_queue; // 0x28 sz:0x10 + xe::be device_lock; // 0x38 sz:0x10 + xe::be start_io_count; // 0x48 sz:0x4 + xe::be start_io_key; // 0x4C sz:0x4 +}; +static_assert_size(X_DEVICE_OBJECT, 0x50); + +dword_result_t IoCreateDevice_entry(pointer_t driver_object, dword_t device_extension_size, pointer_t device_name, dword_t device_type, @@ -708,27 +810,22 @@ dword_result_t IoCreateDevice_entry(dword_t driver_object, lpdword_t device_object, const ppc_context_t& ctx) { // Called from XMountUtilityDrive XAM-task code - // That code tries writing things to a pointer at out_struct+0x18 // We'll alloc some scratch space for it so it doesn't cause any exceptions + auto kernel_mem = ctx->kernel_state->memory(); - // 0x24 is guessed size from accesses to out_struct - likely incorrect - auto current_kernel = ctx->kernel_state; - - uint32_t required_size = 80 + xe::align(device_extension_size, 8); - - auto kernel_mem = current_kernel->memory(); + uint32_t required_size = + sizeof(X_DEVICE_OBJECT) + xe::align(device_extension_size, 8); auto out_guest = kernel_mem->SystemHeapAlloc(required_size); - auto out = kernel_mem->TranslateVirtual(out_guest); + auto out = kernel_mem->TranslateVirtual(out_guest); memset(out, 0, required_size); - xe::store(out, 3); // maybe device object's Ob type? + out->type = 3; // maybe device object's Ob type? // this stores the total object size, without alignment! - - xe::store_and_swap(out + 2, device_extension_size + 80); + out->device_extension_size = device_extension_size + sizeof(X_DEVICE_OBJECT); // from 17559 if (device_type == 7 || device_type == 58 || device_type == 62 || @@ -737,28 +834,27 @@ dword_result_t IoCreateDevice_entry(dword_t driver_object, device_type == 65 || device_type == 66 || device_type == 67 || device_type == 68 || device_type == 69 || device_type == 70 || device_type == 72 || device_type == 73) { - xe::store_and_swap(out + 0xC, 0); + out->mounted_or_self_device = 0; } else { - // pointer to itself? - xe::store_and_swap(out + 0xC, out_guest); + out->mounted_or_self_device = static_cast(out_guest); } - xe::store(out + 0x1C, static_cast(device_type)); + out->device_type = static_cast(device_type); uint32_t flags_field_value = 16; if (device_name) { flags_field_value |= 8; } - xe::store(out + 0x1e, 1); - xe::store_and_swap(out + 0x14, flags_field_value); + out->stack_size = 1; + out->flags = flags_field_value; if (device_extension_size != 0) { // pointer to device specific data - // XMountUtilityDrive writes some kind of header here - xe::store_and_swap(out + 0x18, out_guest + 80); + // XMountUtilityDrive writes some kind of header here + out->device_extension_ptr = out_guest + 80; } - xe::store_and_swap(out + 8, driver_object); + out->drive_object_ptr = static_cast(driver_object); - *device_object = out_guest; + *device_object = static_cast(out_guest); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(IoCreateDevice, kFileSystem, kStub); @@ -766,7 +862,8 @@ DECLARE_XBOXKRNL_EXPORT1(IoCreateDevice, kFileSystem, kStub); // supposed to invoke a callback on the driver object! its some sort of // destructor function intended to be called for all devices created from the // driver -void IoDeleteDevice_entry(dword_t device_ptr, const ppc_context_t& ctx) { +void IoDeleteDevice_entry(pointer_t device_ptr, + const ppc_context_t& ctx) { if (device_ptr) { auto kernel_mem = ctx->kernel_state->memory(); kernel_mem->SystemHeapFree(device_ptr);