Significantly extended IO capabilities. Fixed some random linker bugs and such.

This commit is contained in:
Cody Brocious 2016-05-19 01:50:22 -06:00
parent 96d5f487ff
commit a32a786890
17 changed files with 326 additions and 33 deletions

View file

@ -151,6 +151,10 @@ void Cpu::run(uint32_t eip) {
auto swap = true;
do {
if(break_in) {
box->debugger->enter();
break_in = false;
}
auto exit = hv->enter();
switch (exit.reason) {

View file

@ -31,4 +31,5 @@ public:
uint8_t *mem, *kmem;
int single_step = 0;
bool stop = false;
bool break_in = false;
};

View file

@ -47,15 +47,57 @@ uint32_t Hypercall::query_eeprom(uint32_t index) {
return 0;
}
uint32_t Hypercall::io_open(uint32_t dir_handle, uint32_t fn) {
uint32_t Hypercall::io_open(uint32_t dir_handle, uint32_t fn, FSFlags flags) {
auto fnstr = read_string(fn);
if(dir_handle != 0) {
auto dirhnd = box->hm->get<DirHandle>(dir_handle);
assert(dirhnd->type == IOType::IO_DIRECTORY);
fnstr = dirhnd->path + "\\" + fnstr;
}
auto file = box->io->open(fnstr);
auto file = box->io->open(fnstr, flags);
if(file == NULL)
return 0;
return file->handle;
}
bool Hypercall::io_read(uint32_t handle, uint32_t buf, uint32_t count, int64_t offset) {
auto nbuf = new uint8_t[count];
auto hnd = box->hm->get<IOHandle>(handle);
hnd->read(nbuf, count, offset);
box->cpu->write_memory(buf, count, nbuf);
delete nbuf;
return true;
}
bool Hypercall::io_write(uint32_t handle, uint32_t buf, uint32_t count, int64_t offset) {
auto nbuf = new uint8_t[count];
box->cpu->read_memory(buf, count, nbuf);
auto hnd = box->hm->get<IOHandle>(handle);
hnd->write(nbuf, count, offset);
delete nbuf;
return true;
}
bool Hypercall::io_ioctl(uint32_t handle, uint32_t code, uint32_t ibuf, uint32_t isize, uint32_t obuf, uint32_t osize) {
auto irb = isize != 0 ? new uint8_t[isize] : NULL;
auto orb = osize != 0 ? new uint8_t[osize] : NULL;
if(orb) memset(orb, 0, osize);
box->cpu->read_memory(ibuf, isize, irb);
auto hnd = box->hm->get<IOHandle>(handle);
hnd->ioctl(code, irb, isize, orb, osize);
box->cpu->write_memory(obuf, osize, orb);
if(isize != 0) delete irb;
if(osize != 0) delete orb;
return true;
}
void Hypercall::close(uint32_t handle) {
box->hm->remove(handle);
}
void Hypercall::get_system_time(uint32_t addr) {
timeval stime;
gettimeofday(&stime, NULL);
auto time = ((uint64_t) stime.tv_sec) * 10000000 + ((uint64_t) stime.tv_usec) * 10;
box->cpu->write_memory<uint64_t>(addr, time);
}

View file

@ -12,13 +12,14 @@ list<string> parse_path(string path) {
}
IOManager::IOManager() {
root = make_shared<Directory>();
root = make_shared<Directory>("/");
auto dirs = {
"/Device",
"/Device/CdRom0",
"/Device/Harddisk0",
"/Device/Harddisk0/partition0",
"/Device/Harddisk0/partition1",
"/Device/Harddisk0/partition3",
};
for(auto dir : dirs)
create_directory(dir);
@ -31,16 +32,24 @@ IOManager::IOManager() {
create_link("U:", "/Device/Harddisk0/partition1/UDATA");
}
shared_ptr<IOHandle> IOManager::open(string pathstr) {
shared_ptr<IOHandle> IOManager::open(string pathstr, FSFlags flags) {
auto path = parse_path(pathstr);
auto dir = lookup_directory(pathstr);
if(dir != NULL)
if(dir != NULL) {
return dir->open();
}
auto mapped = lookup_map(pathstr);
auto file = static_pointer_cast<IOHandle>(make_shared<FileHandle>(pathstr, mapped));
box->hm->add(file);
return file;
if(mapped == "")
return NULL;
shared_ptr<IOHandle> hnd;
if(FLAG(flags, FSFlags::DIRECTORY))
hnd = static_pointer_cast<IOHandle>(make_shared<DirHandle>(pathstr, mapped, flags));
else
hnd = static_pointer_cast<IOHandle>(make_shared<FileHandle>(pathstr, mapped, flags));
box->hm->add(hnd);
return hnd;
}
shared_ptr<Directory> IOManager::lookup_directory(string path) {
@ -51,7 +60,7 @@ shared_ptr<Directory> IOManager::lookup_directory(list<string> path) {
auto dir = root;
for(auto e : path) {
if(dir->subdirectories.find(e) == dir->subdirectories.end()) {
cout << "Could not find " << e << " in path " << join(path, "\\") << endl;
//cout << "Could not find " << e << " in path " << join(path, "\\") << endl;
return NULL;
}
@ -79,10 +88,10 @@ string IOManager::lookup_map(string pathstr) {
}
} else {
cout << "Could not find " << e << " in path " << pathstr << endl;
return NULL;
return "";
}
}
return NULL;
return "";
}
shared_ptr<Directory> IOManager::create_directory(string path) {
@ -91,7 +100,7 @@ shared_ptr<Directory> IOManager::create_directory(string path) {
p.pop_back();
auto dir = lookup_directory(p);
auto ndir = make_shared<Directory>();
auto ndir = make_shared<Directory>(path);
dir->subdirectories[dn] = ndir;
return ndir;
}
@ -119,8 +128,11 @@ void IOManager::create_map(string from, string to) {
dir->dirmaps[fn] = to;
}
Directory::Directory(string path) : path(path) {
}
shared_ptr<IOHandle> Directory::open() {
auto hnd = static_pointer_cast<IOHandle>(make_shared<DirHandle>(path));
auto hnd = static_pointer_cast<IOHandle>(make_shared<DirHandle>(path, "", FSFlags::READ | FSFlags::DIRECTORY));
box->hm->add(hnd);
return hnd;
}
@ -128,17 +140,63 @@ shared_ptr<IOHandle> Directory::open() {
IOHandle::IOHandle(IOType type, string path) : type(type), path(path) {
}
FileHandle::FileHandle(string path, string mapped_path) : IOHandle(IOType::IO_FILE, path), mapped_path(mapped_path) {
FileHandle::FileHandle(string path, string mapped_path, FSFlags flags) : IOHandle(IOType::IO_FILE, path), mapped_path(mapped_path) {
cout << "Creating file handle for virtual path " << path << " to real path " << mapped_path << endl;
writable = FLAG(flags, FSFlags::WRITE);
fd = open(mapped_path.c_str(), (writable ? O_RDWR : O_RDONLY) | (FLAG(flags, FSFlags::CREATE) ? O_CREAT : 0));
cout << "FD " << dec << fd << endl;
bailout(fd == -1);
}
void FileHandle::read() {
void FileHandle::read(void *buf, uint32_t count, int64_t offset) {
bailout(offset != -1);
::read(fd, buf, count);
}
void FileHandle::write() {
void FileHandle::write(void *buf, uint32_t count, int64_t offset) {
bailout(offset != -1);
::write(fd, buf, count);
}
void FileHandle::ioctl(uint32_t code, void *ibuf, uint32_t isize, void *obuf, uint32_t osize) {
cout << "Attempted ioctl on file " << path << endl;
cout << format("Code: %08x") % code << endl;
}
void FileHandle::close() {
}
DirHandle::DirHandle(string path) : IOHandle(IOType::IO_DIRECTORY, path) {
DirHandle::DirHandle(string path, string mapped_path, FSFlags flags) : IOHandle(IOType::IO_DIRECTORY, path) {
if(mapped_path != "" && FLAG(flags, FSFlags::CREATE))
mkdir(mapped_path.c_str(), 0700);
}
void DirHandle::read(void *buf, uint32_t count, int64_t offset) {
cout << "Attempting to read " << count << " bytes from directory " << path << endl;
cout << "Offset " << hex << offset << endl;
}
void DirHandle::write(void *buf, uint32_t count, int64_t offset) {
cout << "Attempting to write " << count << " bytes to directory " << path << endl;
cout << "Offset " << hex << offset << endl;
if(count == 0) {
cout << "Null write" << endl;
box->cpu->break_in = true;
}
}
void DirHandle::ioctl(uint32_t code, void *ibuf, uint32_t isize, void *obuf, uint32_t osize) {
switch(code) {
case IOCTL_DISK_GET_PARTITION_INFO: {
auto part = (PARTITION_INFORMATION *) obuf;
part->StartingOffset = 0;
part->PartitionLength = 1 * 1024 * 1024 * 1024; // 1GB
part->HiddenSectors = 0;
part->PartitionNumber = 5; // Who cares?
part->PartitionType = 0;
part->BootIndicator = 1;
part->RecognizedPartition = 1;
part->RewritePartition = 0;
break;
}
default:
cout << "Attempted unknown ioctl on dir " << path << endl;
cout << format("Code: %08x") % code << endl;
break;
}
}
void DirHandle::close() {
}

View file

@ -10,28 +10,39 @@ enum IOType {
class IOHandle : public Handle {
public:
IOHandle(IOType type, string path);
virtual void read(void *buf, uint32_t count, int64_t offset) = 0;
virtual void write(void *buf, uint32_t count, int64_t offset) = 0;
virtual void ioctl(uint32_t code, void *ibuf, uint32_t isize, void *obuf, uint32_t osize) = 0;
virtual void close() = 0;
IOType type;
string path;
};
class FileHandle : public IOHandle {
public:
FileHandle(string path, string mapped_path);
void read();
void write();
FileHandle(string path, string mapped_path, FSFlags flags);
void read(void *buf, uint32_t count, int64_t offset);
void write(void *buf, uint32_t count, int64_t offset);
void ioctl(uint32_t code, void *ibuf, uint32_t isize, void *obuf, uint32_t osize);
void close();
string mapped_path;
bool writable;
int fd;
};
class DirHandle : public IOHandle {
public:
DirHandle(string path);
DirHandle(string path, string mapped_path, FSFlags flags);
void read(void *buf, uint32_t count, int64_t offset);
void write(void *buf, uint32_t count, int64_t offset);
void ioctl(uint32_t code, void *ibuf, uint32_t isize, void *obuf, uint32_t osize);
void close();
};
class Directory {
public:
Directory(string path);
shared_ptr<IOHandle> open();
map<string, shared_ptr<Directory>> subdirectories;
@ -42,8 +53,7 @@ public:
class IOManager {
public:
IOManager();
shared_ptr<IOHandle> open(string fn);
shared_ptr<IOHandle> open_file(string path);
shared_ptr<IOHandle> open(string fn, FSFlags flags);
shared_ptr<Directory> lookup_directory(string path);
shared_ptr<Directory> lookup_directory(list<string> path);

9
Ioctls.hpp Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#define IOCTL_DISK_GET_PARTITION_INFO 0x74004
typedef struct __attribute__((packed)) PARTITION_INFORMATION {
uint64_t StartingOffset, PartitionLength;
uint32_t HiddenSectors, PartitionNumber;
uint8_t PartitionType, BootIndicator, RecognizedPartition, RewritePartition;
} PARTITION_INFORMATION;

View file

@ -3,12 +3,12 @@
#define halt() do { asm("hlt"); } while(0)
#define NTAPI __attribute__((stdcall))
#include <stdint.h>
#include <stdarg.h>
#include "mini-printf.hpp"
#include "Log.hpp"
#include "C.hpp"
#include "../Shared.hpp"
#include "../xbetypes.hpp"
#include "XboxKernel/nttypes.hpp"
#include "TIB.hpp"

View file

@ -9,8 +9,13 @@ NTSTATUS NTAPI kernel_NtOpenFile(
uint32_t OpenOptions
) {
log("NtOpenFile('%s', 0x%08x, 0x%08x)", ObjectAttributes->ObjectName->Buffer, DesiredAccess, OpenOptions);
auto flags = FSFlags::READ;
if(FLAG(DesiredAccess, FILE_WRITE_DATA))
flags |= FSFlags::WRITE;
if(FLAG(OpenOptions, FILE_DIRECTORY_FILE))
flags |= FSFlags::DIRECTORY;
*FileHandle = io_open(ObjectAttributes->RootDirectory, (char *) ObjectAttributes->ObjectName->Buffer);
*FileHandle = io_open(ObjectAttributes->RootDirectory, (char *) ObjectAttributes->ObjectName->Buffer, flags);
if(*FileHandle == 0)
return STATUS_OBJECT_NAME_NOT_FOUND;
return STATUS_SUCCESS;
@ -33,15 +38,76 @@ NTSTATUS NTAPI kernel_NtCreateFile(
CreateDisposition,
CreateOptions
);
*FileHandle = io_open(ObjectAttributes->RootDirectory, (char *) ObjectAttributes->ObjectName->Buffer);
auto flags = FSFlags::READ;
if(CreateDisposition == FILE_CREATE || CreateDisposition == FILE_OPEN_IF)
flags |= FSFlags::CREATE;
else if(CreateDisposition == FILE_OVERWRITE || CreateDisposition == FILE_OVERWRITE_IF)
flags |= FSFlags::OVERWRITE;
if(FLAG(DesiredAccess, FILE_WRITE_DATA))
flags |= FSFlags::WRITE;
if(FLAG(CreateOptions, FILE_DIRECTORY_FILE))
flags |= FSFlags::DIRECTORY;
*FileHandle = io_open(ObjectAttributes->RootDirectory, (char *) ObjectAttributes->ObjectName->Buffer, flags);
if(*FileHandle == 0) {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
return STATUS_SUCCESS;
}
NTSTATUS NTAPI kernel_NtReadFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset
) {
auto offset = (ByteOffset == NULL || ByteOffset->u.HighPart == -1) ? -1 : ByteOffset->QuadPart;
if(io_read(FileHandle, Buffer, Length, offset))
return STATUS_SUCCESS;
bailout("Unknown failure");
return -1;
}
NTSTATUS NTAPI kernel_NtWriteFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset
) {
auto offset = (ByteOffset == NULL || ByteOffset->u.HighPart == -1) ? -1 : ByteOffset->QuadPart;
if(io_write(FileHandle, Buffer, Length, offset))
return STATUS_SUCCESS;
bailout("Unknown failure");
return -1;
}
NTSTATUS NTAPI kernel_NtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputLength,
PVOID OutputBuffer,
ULONG OutputLength
) {
if(io_ioctl(FileHandle, IoControlCode, InputBuffer, InputLength, OutputBuffer, OutputLength))
return STATUS_SUCCESS;
bailout("Unknown failure");
return -1;
}
NTSTATUS NTAPI kernel_NtClose(HANDLE handle) {
log("NtClose %08x", handle);
close(handle);
return STATUS_SUCCESS;
}
@ -79,3 +145,5 @@ NTSTATUS NTAPI kernel_IoCreateSymbolicLink(
log("IoCreateSymbolicLink('%s', '%s')", SymbolicLinkName->Buffer, DeviceName->Buffer);
return STATUS_SUCCESS;
}
uint32_t kernel_HalDiskCachePartitionCount = 1;

View file

@ -1,6 +1,9 @@
#pragma once
#include "Kernel.hpp"
// ACCESS_MASK
#define FILE_WRITE_DATA 0x00000002
// CreateDisposition
#define FILE_SUPERSEDE 0x00000000
#define FILE_OPEN 0x00000001
@ -47,6 +50,41 @@ NTSTATUS NTAPI kernel_NtOpenFile(
uint32_t OpenOptions
);
NTSTATUS NTAPI kernel_NtReadFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset
);
NTSTATUS NTAPI kernel_NtWriteFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset
);
NTSTATUS NTAPI kernel_NtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PVOID ApcRoutine,
PVOID ApcContext,
PVOID IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputLength,
PVOID OutputBuffer,
ULONG OutputLength
);
NTSTATUS NTAPI kernel_NtClose(HANDLE handle);
NTSTATUS NTAPI kernel_NtQueryVolumeInformationFile(
@ -73,3 +111,5 @@ NTSTATUS NTAPI kernel_NtCreateFile(
IN ULONG CreateDisposition,
IN ULONG CreateOptions
);
extern uint32_t kernel_HalDiskCachePartitionCount;

View file

@ -26,7 +26,7 @@ void kernel_DbgPrint(char *format, ...) {
void NTAPI kernel_RtlAssert(char *message, char *filename, uint32_t line, uint32_t unk) {
if(message == NULL) message = (char *) "~NULL~";
if(filename == NULL) filename = (char *) "~NULL~";
log("Failed assert %s in %s on line %i (unknown %i == 0x%x)", message, filename, line, unk, unk);
log("Failed assert %s in %s on line %i", message, filename, line);
halt();
}
@ -63,3 +63,7 @@ NTSTATUS NTAPI kernel_ExQueryNonVolatileSetting(
ULONG NTAPI kernel_RtlNtStatusToDosError(NTSTATUS Status) {
return 0;
}
void NTAPI kernel_KeQuerySystemTime(uint64_t *time) {
get_system_time(time);
}

View file

@ -24,3 +24,5 @@ NTSTATUS NTAPI kernel_ExQueryNonVolatileSetting(
);
ULONG NTAPI kernel_RtlNtStatusToDosError(NTSTATUS Status);
void NTAPI kernel_KeQuerySystemTime(uint64_t *time);

View file

@ -141,11 +141,6 @@ typedef enum _KOBJECTS {
} KOBJECTS, *PKOBJECTS;
typedef union _ULARGE_INTEGER {
struct {
DWORD LowPart;
DWORD HighPart;
} u1;
struct {
DWORD LowPart;
DWORD HighPart;

View file

@ -31,6 +31,9 @@ start:
.Lhang:
jmp .Lhang
.section __DATA, __data
.long 0xDEADBEEF # Prevent __data from ending up after __ass
.section __DATA, __ass
bss:
.skip 16384 # 16 KiB

22
Shared.hpp Normal file
View file

@ -0,0 +1,22 @@
#pragma once
enum class FSFlags : int {
READ = 0,
WRITE = 1,
CREATE = 2,
OVERWRITE = 4,
DIRECTORY = 8
};
inline FSFlags operator|(FSFlags a, FSFlags b) {
return static_cast<FSFlags>(static_cast<int>(a) | static_cast<int>(b));
}
inline FSFlags operator&(FSFlags a, FSFlags b) {
return static_cast<FSFlags>(static_cast<int>(a) & static_cast<int>(b));
}
inline FSFlags& operator |=(FSFlags& a, FSFlags b) {
return a = a | b;
}
#define FLAG(val, flag) (((val) & (flag)) == (flag))

View file

@ -8,6 +8,8 @@
#include <iomanip>
#include <cassert>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <list>
using namespace std;
using boost::format;
@ -25,6 +27,7 @@ using namespace boost::algorithm;
#include "Mac/HVMac.hpp"
#endif
#include "Shared.hpp"
#include "Hypercall.hpp"
#include "xbetypes.hpp"
#include "Xbe.hpp"
@ -32,6 +35,7 @@ using namespace boost::algorithm;
#include "HandleManager.hpp"
#include "PageManager.hpp"
#include "ThreadManager.hpp"
#include "Ioctls.hpp"
#include "IOManager.hpp"
#include "Debugger.hpp"
#include "Box.hpp"

View file

@ -26,3 +26,28 @@ io_open:
- return: uint32_t
- dir_handle: uint32_t
- fn: char *
- flags: FSFlags
io_read:
- return: bool
- handle: uint32_t
- buf: void *
- count: uint32_t
- offset: int64_t
io_write:
- return: bool
- handle: uint32_t
- buf: void *
- count: uint32_t
- offset: int64_t
io_ioctl:
- return: bool
- handle: uint32_t
- code: uint32_t
- ibuf: void *
- isize: uint32_t
- obuf: void *
- osize: uint32_t
close:
- handle: uint32_t
get_system_time:
- time: uint64_t *

View file

@ -43,6 +43,10 @@ uint32_t load_kernel(Cpu *cpu) {
return entry;
}
void intHandler(int _) {
box->cpu->break_in = true;
}
int main(int argc, char **argv) {
new Box;
@ -50,6 +54,8 @@ int main(int argc, char **argv) {
auto xbe = new Xbe((char *) "test1.xbe");
xbe->LoadImage();
signal(SIGINT, intHandler);
box->cpu->run(entry);
return 0;