make block device information accessible in API

This commit is contained in:
nakst 2021-09-11 20:59:01 +01:00
parent 98cb1c0400
commit 485dbc59e5
19 changed files with 294 additions and 120 deletions

View File

@ -1,12 +1,24 @@
#define INSTALLER
#define ES_CRT_WITHOUT_PREFIX
#include <essence.h>
#include <ports/lzma/LzmaDec.c>
#include <shared/hash.cpp>
#include <ports/lzma/LzmaDec.c>
#include <shared/array.cpp>
#define IMPLEMENTATION
#include <shared/array.cpp>
#undef IMPLEMENTATION
#define Log(...)
#define exit(x) EsThreadTerminate(ES_CURRENT_THREAD)
#include <shared/esfs2.h>
Array<EsMessageDevice> connectedDrives;
/////////////////////////////////////////////
#define BUFFER_SIZE (1048576)
#define NAME_MAX (4096)
@ -115,17 +127,55 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
}
void ReadBlock(uint64_t, uint64_t, void *) {
// TODO.
}
void WriteBlock(uint64_t, uint64_t, void *) {
// TODO.
}
void WriteBytes(uint64_t, uint64_t, void *) {
// TODO.
}
void ConnectedDriveAdd(EsMessageDevice device) {
if (device.type != ES_DEVICE_BLOCK) {
return;
}
EsBlockDeviceInformation information;
EsDeviceControl(device.handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
if (information.nestLevel) {
return;
}
connectedDrives.Add(device);
}
void ConnectedDriveRemove(EsMessageDevice device) {
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
if (connectedDrives[i].id == device.id) {
connectedDrives.Delete(i);
return;
}
}
}
void _start() {
_init();
EsPerformanceTimerPush();
EsAssert(ES_SUCCESS == Extract(EsLiteral("0:/installer_archive.dat"), EsLiteral("0:/extracted")));
EsPrint("time: %Fs\n", EsPerformanceTimerPop());
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
ConnectedDriveAdd(device);
}, 0);
while (true) {
EsMessage *message = EsMessageReceive();
if (message->type == ES_MSG_DEVICE_CONNECTED) {
ConnectedDriveAdd(message->device);
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
ConnectedDriveRemove(message->device);
}
}
}

View File

@ -113,7 +113,9 @@ struct Timer {
struct {
Array<EsSystemConfigurationGroup> systemConfigurationGroups;
EsMutex systemConfigurationMutex;
Array<MountPoint> mountPoints;
Array<EsMessageDevice> connectedDevices;
bool foundBootFileSystem;
EsProcessStartupInformation *startupInformation;
GlobalData *global;
@ -254,12 +256,22 @@ bool EsMountPointGetVolumeInformation(const char *prefix, size_t prefixBytes, Es
}
void EsMountPointEnumerate(EsMountPointEnumerationCallback callback, EsGeneric context) {
EsMessageMutexCheck();
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
MountPoint *mountPoint = &api.mountPoints[i];
callback(mountPoint->prefix, mountPoint->prefixBytes, context);
}
}
void EsDeviceEnumerate(EsDeviceEnumerationCallback callback, EsGeneric context) {
EsMessageMutexCheck();
for (uintptr_t i = 0; i < api.connectedDevices.Length(); i++) {
callback(api.connectedDevices[i], context);
}
}
EsError NodeOpen(const char *path, size_t pathBytes, uint32_t flags, _EsNodeInformation *node) {
EsMountPoint *mountPoint = NodeFindMountPoint(path, pathBytes);
@ -1060,6 +1072,17 @@ EsMessage *EsMessageReceive() {
return &message.message;
}
}
} else if (type == ES_MSG_DEVICE_CONNECTED) {
api.connectedDevices.Add(message.message.device);
return &message.message;
} else if (type == ES_MSG_DEVICE_DISCONNECTED) {
for (uintptr_t i = 0; i < api.connectedDevices.Length(); i++) {
if (api.connectedDevices[i].id == message.message.device.id) {
EsHandleClose(api.connectedDevices[i].handle);
api.connectedDevices.Delete(i);
return &message.message;
}
}
} else if (type == ES_MSG_INSTANCE_DESTROY) {
APIInstance *instance = (APIInstance *) message.message.instanceDestroy.instance->_private;
@ -1263,6 +1286,18 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
EsHeapFree(initialMountPoints);
EsHandleClose(initialMountPointsBuffer);
EsHandle initialDevicesBuffer = api.startupInformation->data.initialDevices;
size_t initialDevicesCount = EsConstantBufferGetSize(initialDevicesBuffer) / sizeof(EsMessageDevice);
EsMessageDevice *initialDevices = (EsMessageDevice *) EsHeapAllocate(initialDevicesCount * sizeof(EsMessageDevice), false);
EsConstantBufferRead(initialDevicesBuffer, initialDevices);
for (uintptr_t i = 0; i < initialDevicesCount; i++) {
api.connectedDevices.Add(initialDevices[i]);
}
EsHeapFree(initialDevices);
EsHandleClose(initialDevicesBuffer);
uint8_t m = DESKTOP_MSG_SYSTEM_CONFIGURATION_GET;
EsBuffer responseBuffer = { .canGrow = true };
MessageDesktop(&m, 1, ES_INVALID_HANDLE, &responseBuffer);

View File

@ -175,7 +175,6 @@ struct {
Array<InstalledApplication *> installedApplications;
Array<ApplicationInstance *> allApplicationInstances;
Array<ContainerWindow *> allContainerWindows;
Array<EsMessageDevice> connectedDevices;
InstalledApplication *fileManager;
@ -1233,6 +1232,7 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
arguments.permissions = ES_PERMISSION_WINDOW_MANAGER;
Array<EsMountPoint> initialMountPoints = {};
Array<EsMessageDevice> initialDevices = {};
Array<EsHandle> handleDuplicateList = {};
Array<uint32_t> handleModeDuplicateList = {};
_EsNodeInformation settingsNode = {};
@ -1270,6 +1270,14 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
handleModeDuplicateList.Add(2 /* prevent write */);
}
if (application->permissions & APPLICATION_PERMISSION_ALL_DEVICES) {
for (uintptr_t i = 0; i < api.connectedDevices.Length(); i++) {
initialDevices.Add(api.connectedDevices[i]);
handleDuplicateList.Add(api.connectedDevices[i].handle);
handleModeDuplicateList.Add(0);
}
}
{
error = NodeOpen(application->settingsPath, application->settingsPathBytes,
ES_NODE_DIRECTORY | ES_NODE_CREATE_DIRECTORIES | _ES_NODE_DIRECTORY_WRITE, &settingsNode);
@ -1291,6 +1299,10 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
handleDuplicateList.Add(arguments.data.initialMountPoints);
handleModeDuplicateList.Add(0);
arguments.data.initialDevices = EsConstantBufferCreate(initialDevices.array, initialDevices.Length() * sizeof(EsMessageDevice), ES_CURRENT_PROCESS);
handleDuplicateList.Add(arguments.data.initialDevices);
handleModeDuplicateList.Add(0);
arguments.handles = handleDuplicateList.array;
arguments.handleModes = handleModeDuplicateList.array;
arguments.handleCount = handleDuplicateList.Length();
@ -1300,6 +1312,7 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
EsHandleClose(arguments.executable);
initialMountPoints.Free();
initialDevices.Free();
handleDuplicateList.Free();
handleModeDuplicateList.Free();
@ -1307,6 +1320,14 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
EsHandleClose(settingsNode.handle);
}
if (arguments.data.initialMountPoints) {
EsHandleClose(arguments.data.initialMountPoints);
}
if (arguments.data.initialDevices) {
EsHandleClose(arguments.data.initialDevices);
}
if (!ES_CHECK_ERROR(error)) {
process = information.handle;
EsHandleClose(information.mainThread.handle);
@ -2525,12 +2546,15 @@ void DesktopMessage(EsMessage *message) {
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
desktop.installedApplications[i]->notified = false;
}
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
} else if (message->type == ES_MSG_DEVICE_CONNECTED) {
EsHandle handle = message->device.handle;
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES)
if (instance->application && (instance->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES)
&& instance->processHandle && !instance->application->notified) {
message->device.handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, handle, instance->processHandle, 0, 0);
EsMessagePostRemote(instance->processHandle, message);
if (instance->application->useSingleProcess) instance->application->notified = true;
}
@ -2539,19 +2563,33 @@ void DesktopMessage(EsMessage *message) {
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
desktop.installedApplications[i]->notified = false;
}
} else if (message->type == ES_MSG_DEVICE_CONNECTED) {
desktop.connectedDevices.Add(message->device);
// TODO Propagate message.
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
for (uintptr_t i = 0; i < desktop.connectedDevices.Length(); i++) {
if (desktop.connectedDevices[i].id == message->device.id) {
EsHandleClose(desktop.connectedDevices[i].handle);
desktop.connectedDevices.Delete(i);
break;
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM || message->type == ES_MSG_DEVICE_DISCONNECTED) {
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
ApplicationInstance *instance = desktop.allApplicationInstances[i];
if (!instance->application) {
continue;
}
if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
if (~instance->application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
continue;
}
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
if (~instance->application->permissions & APPLICATION_PERMISSION_ALL_DEVICES) {
continue;
}
}
if (instance->processHandle && !instance->application->notified) {
EsMessagePostRemote(instance->processHandle, message);
if (instance->application->useSingleProcess) instance->application->notified = true;
}
}
// TODO Propagate message.
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
desktop.installedApplications[i]->notified = false;
}
} else if (message->type == ES_MSG_SET_SCREEN_RESOLUTION) {
if (desktop.setupDesktopUIComplete) {
DesktopSetup(); // Refresh desktop UI.

View File

@ -827,6 +827,7 @@ enum EsSyscallType {
ES_SYSCALL_FILE_CONTROL
ES_SYSCALL_DIRECTORY_ENUMERATE
ES_SYSCALL_VOLUME_GET_INFORMATION
ES_SYSCALL_DEVICE_CONTROL
// Networking.
@ -1126,6 +1127,10 @@ enum EsClipboardFormat {
ES_CLIPBOARD_FORMAT_PATH_LIST
}
enum EsDeviceControlType {
ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION
}
function_pointer int EsUICallback(struct EsElement *element, struct EsMessage *message);
struct EsBuffer {
@ -1251,7 +1256,7 @@ struct EsMountPoint {
};
struct EsProcessCreateData {
EsHandle environment, initialMountPoints;
EsHandle environment, initialMountPoints, initialDevices;
};
struct EsProcessStartupInformation {
@ -1860,6 +1865,17 @@ struct EsFontInformation {
uint16_t availableWeightsItalic;
};
struct EsBlockDeviceInformation {
size_t sectorSize;
EsFileOffset sectorCount;
bool noMBR;
bool readOnly;
uint8_t nestLevel;
uint8_t driveType;
uint8_t modelBytes;
char model[64];
};
// Function pointer types.
function_pointer void EsThreadEntryCallback(EsGeneric argument);
@ -1870,6 +1886,7 @@ function_pointer void EsTimerCallback(EsGeneric argument);
function_pointer void EsMenuCallback(EsMenu *menu, EsGeneric context);
function_pointer void EsUndoCallback(const void *item, EsUndoManager *manager, EsMessage *message);
function_pointer void EsMountPointEnumerationCallback(const char *prefix, size_t prefixBytes, EsGeneric context);
function_pointer void EsDeviceEnumerationCallback(EsMessageDevice device, EsGeneric context);
function_pointer void EsListViewEnumerateVisibleItemsCallback(EsListView *view, EsElement *item, uint32_t group, EsGeneric index);
function_pointer void EsFontEnumerationCallback(const EsFontInformation *information, EsGeneric context);
function_pointer void EsUserTaskCallback(EsUserTask *task, EsGeneric data);
@ -1947,6 +1964,9 @@ function bool EsMountPointGetVolumeInformation(const char *prefix, size_t prefix
function void EsMountPointEnumerate(EsMountPointEnumerationCallback callback, EsGeneric context);
function void _EsPathAnnouncePathMoved(STRING oldPath, STRING newPath);
function void EsDeviceEnumerate(EsDeviceEnumerationCallback callback, EsGeneric context);
function EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, int32_t di, void *dp);
// Processes and threads.
function EsError EsProcessCreate(EsProcessCreationArguments *arguments, EsProcessInformation *information);
@ -1967,8 +1987,8 @@ function void *EsArenaAllocate(EsArena *arena, bool zero); // Not thread-safe.
function void EsArenaFree(EsArena *arena, void *pointer); // Not thread-safe.
function void EsArenaInitialise(EsArena *arena, size_t blockSize, size_t itemSize);
function const void *EsBufferRead(struct EsBuffer *buffer, size_t readBytes);
function bool EsBufferReadInto(struct EsBuffer *buffer, void *destination, size_t readBytes);
function const void *EsBufferRead(EsBuffer *buffer, size_t readBytes);
function bool EsBufferReadInto(EsBuffer *buffer, void *destination, size_t readBytes);
function const void *EsBufferReadMany(struct EsBuffer *buffer, size_t a, size_t b);
function int32_t EsBufferReadInt32Endian(EsBuffer *buffer, int32_t errorValue);
function void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writeBytes);

View File

@ -534,7 +534,7 @@ long EsPOSIXSystemCall(long n, long a1, long a2, long a3, long a4, long a5, long
double timeStampMs = EsTimeStampMs();
uint64_t ns = timeStampMs * 1e6;
tp->tv_sec = ns / 1000000000;
tp->tv_nsec = (ns % 1000000000) * 1000;
tp->tv_nsec = ns % 1000000000;
} break;
case SYS_wait4: {

View File

@ -903,3 +903,7 @@ size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes) {
size_t EsPipeWrite(EsHandle pipe, const void *buffer, size_t bytes) {
return EsSyscall(ES_SYSCALL_PIPE_WRITE, pipe, (uintptr_t) buffer, bytes, 0);
}
EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, int32_t di, void *dp) {
return EsSyscall(ES_SYSCALL_DEVICE_CONTROL, handle, type, di, (uintptr_t) dp);
}

View File

@ -835,13 +835,15 @@ void AHCIController::Initialise() {
device->controller = this;
device->port = i;
device->sectorSize = ports[i].sectorBytes;
device->sectorCount = ports[i].sectorCount;
device->maxAccessSectorCount = ports[i].atapi ? (65535 / device->sectorSize)
: ((PRDT_ENTRY_COUNT - 1 /* need one extra if not page aligned */) * K_PAGE_SIZE / device->sectorSize);
device->readOnly = ports[i].atapi;
device->cModel = ports[i].model;
device->driveType = ports[i].atapi ? ES_DRIVE_TYPE_CDROM : ports[i].ssd ? ES_DRIVE_TYPE_SSD : ES_DRIVE_TYPE_HDD;
device->information.sectorSize = ports[i].sectorBytes;
device->information.sectorCount = ports[i].sectorCount;
device->maxAccessSectorCount = ports[i].atapi ? (65535 / device->information.sectorSize)
: ((PRDT_ENTRY_COUNT - 1 /* need one extra if not page aligned */) * K_PAGE_SIZE / device->information.sectorSize);
device->information.readOnly = ports[i].atapi;
EsAssert(sizeof(ports[i].model) <= sizeof(device->information.model));
EsMemoryCopy(device->information.model, ports[i].model, sizeof(ports[i].model));
device->information.modelBytes = sizeof(ports[i].model);
device->information.driveType = ports[i].atapi ? ES_DRIVE_TYPE_CDROM : ports[i].ssd ? ES_DRIVE_TYPE_SSD : ES_DRIVE_TYPE_HDD;
device->access = [] (KBlockDeviceAccessRequest request) {
AHCIDrive *drive = (AHCIDrive *) request.device;

View File

@ -1833,7 +1833,7 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
return false;
}
if (volume->block->readOnly) {
if (volume->block->information.readOnly) {
volume->readOnly = true;
}
@ -1846,8 +1846,8 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
ESFS_CHECK_FATAL(0 == EsMemoryCompare(volume->superblock.signature, ESFS_SIGNATURE_STRING, 16), "Invalid superblock signature.");
ESFS_CHECK_FATAL(volume->superblock.requiredReadVersion <= ESFS_DRIVER_VERSION, "Incompatible file system version.");
ESFS_CHECK_FATAL(superblock->blockSize >= 1024 && superblock->blockSize <= 16384 && (superblock->blockSize % volume->block->sectorSize) == 0, "Invalid block size.");
ESFS_CHECK_FATAL(superblock->blockCount * superblock->blockSize / volume->block->sectorSize <= volume->block->sectorCount, "More blocks than drive.");
ESFS_CHECK_FATAL(superblock->blockSize >= 1024 && superblock->blockSize <= 16384 && (superblock->blockSize % volume->block->information.sectorSize) == 0, "Invalid block size.");
ESFS_CHECK_FATAL(superblock->blockCount * superblock->blockSize / volume->block->information.sectorSize <= volume->block->information.sectorCount, "More blocks than drive.");
ESFS_CHECK_FATAL(superblock->blocksUsed <= superblock->blockCount, "More blocks used than exist.");
ESFS_CHECK_FATAL(superblock->blocksPerGroup <= 65536 && superblock->blocksPerGroup < superblock->blockCount && superblock->blocksPerGroup >= 1024, "Invalid block group size.");
ESFS_CHECK_FATAL((superblock->groupCount - 1) * superblock->blocksPerGroup <= superblock->blockCount, "Invalid number of block groups.");

View File

@ -140,16 +140,16 @@ static bool Mount(Volume *volume) {
// Load the superblock.
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(volume->block->sectorSize, false, K_FIXED);
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(volume->block->information.sectorSize, false, K_FIXED);
if (!sectorBuffer) {
MOUNT_FAILURE("Could not allocate buffer.\n");
}
EsDefer(EsHeapFree(sectorBuffer, volume->block->sectorSize, K_FIXED));
EsDefer(EsHeapFree(sectorBuffer, volume->block->information.sectorSize, K_FIXED));
{
if (!volume->Access(1024, volume->block->sectorSize, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
if (!volume->Access(1024, volume->block->information.sectorSize, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not read boot sector.\n");
}
@ -169,7 +169,7 @@ static bool Mount(Volume *volume) {
volume->blockBytes = 1024 << volume->superBlock.blockSizeExponent;
if (volume->blockBytes < volume->block->sectorSize) {
if (volume->blockBytes < volume->block->information.sectorSize) {
MOUNT_FAILURE("Block size smaller than drive sector size.\n");
}
}
@ -201,14 +201,14 @@ static bool Mount(Volume *volume) {
uint32_t blockGroup = (inode - 1) / volume->superBlock.inodesPerBlockGroup;
uint32_t indexInInodeTable = (inode - 1) % volume->superBlock.inodesPerBlockGroup;
uint32_t sectorInInodeTable = (indexInInodeTable * volume->superBlock.inodeStructureBytes) / volume->block->sectorSize;
uint32_t offsetInSector = (indexInInodeTable * volume->superBlock.inodeStructureBytes) % volume->block->sectorSize;
uint32_t sectorInInodeTable = (indexInInodeTable * volume->superBlock.inodeStructureBytes) / volume->block->information.sectorSize;
uint32_t offsetInSector = (indexInInodeTable * volume->superBlock.inodeStructureBytes) % volume->block->information.sectorSize;
BlockGroupDescriptor *blockGroupDescriptor = volume->blockGroupDescriptorTable + blockGroup;
if (!volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
+ sectorInInodeTable * volume->block->sectorSize,
volume->block->sectorSize,
+ sectorInInodeTable * volume->block->information.sectorSize,
volume->block->information.sectorSize,
K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not read the inode table.\n");
}
@ -234,7 +234,7 @@ static bool Mount(Volume *volume) {
}
static uint32_t GetDataBlock(Volume *volume, Inode *node, uint64_t blockIndex, uint8_t *blockBuffer) {
#define CHECK_BLOCK_INDEX() if (offset == 0 || offset / volume->block->sectorSize > volume->block->sectorCount) { \
#define CHECK_BLOCK_INDEX() if (offset == 0 || offset / volume->block->information.sectorSize > volume->block->information.sectorCount) { \
KernelLog(LOG_ERROR, "Ext2", "invalid block index", "GetDataBlock - Block out of bounds.\n"); return 0; }
#define GET_DATA_BLOCK_ACCESS_FAILURE() do { KernelLog(LOG_ERROR, "Ext2", "block access failure", "GetDataBlock - Could not read block.\n"); return 0; } while (0)
@ -448,14 +448,14 @@ static EsError Load(KNode *_directory, KNode *node, KNodeMetadata *metadata, con
uint32_t blockGroup = (inode - 1) / volume->superBlock.inodesPerBlockGroup;
uint32_t indexInInodeTable = (inode - 1) % volume->superBlock.inodesPerBlockGroup;
uint32_t sectorInInodeTable = (indexInInodeTable * volume->superBlock.inodeStructureBytes) / volume->block->sectorSize;
uint32_t offsetInSector = (indexInInodeTable * volume->superBlock.inodeStructureBytes) % volume->block->sectorSize;
uint32_t sectorInInodeTable = (indexInInodeTable * volume->superBlock.inodeStructureBytes) / volume->block->information.sectorSize;
uint32_t offsetInSector = (indexInInodeTable * volume->superBlock.inodeStructureBytes) % volume->block->information.sectorSize;
BlockGroupDescriptor *blockGroupDescriptor = volume->blockGroupDescriptorTable + blockGroup;
if (!volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
+ sectorInInodeTable * volume->block->sectorSize,
volume->block->sectorSize,
+ sectorInInodeTable * volume->block->information.sectorSize,
volume->block->information.sectorSize,
K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) {
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
@ -600,9 +600,9 @@ static void DeviceAttach(KDevice *parent) {
return;
}
if (volume->block->sectorSize & 0x1FF) {
if (volume->block->information.sectorSize & 0x1FF) {
KernelLog(LOG_ERROR, "Ext2", "incorrect sector size", "Expected sector size to be a multiple of 512, but drive's sectors are %D.\n",
volume->block->sectorSize);
volume->block->information.sectorSize);
KDeviceDestroy(volume);
return;
}

View File

@ -404,7 +404,7 @@ static bool Mount(Volume *volume) {
sectorsPerFAT * SECTOR_SIZE, K_ACCESS_READ, volume->fat, ES_FLAGS_DEFAULT)) MOUNT_FAILURE("Could not read FAT.\n");
volume->spaceUsed = CountUsedClusters(volume) * superBlock->sectorsPerCluster * superBlock->bytesPerSector;
volume->spaceTotal = volume->block->sectorSize * volume->block->sectorCount;
volume->spaceTotal = volume->block->information.sectorSize * volume->block->information.sectorCount;
volume->rootDirectory->driverNode = EsHeapAllocate(sizeof(FSNode), true, K_FIXED);
if (!volume->rootDirectory->driverNode) MOUNT_FAILURE("Could not allocate root node.\n");
@ -461,7 +461,7 @@ static void DeviceAttach(KDevice *parent) {
return;
}
if (volume->block->sectorSize != SECTOR_SIZE) {
if (volume->block->information.sectorSize != SECTOR_SIZE) {
KernelLog(LOG_ERROR, "FAT", "mount failure", "DeviceAttach - Unsupported sector size.\n");
KDeviceDestroy(volume);
return;

View File

@ -559,11 +559,11 @@ void ATAController::Initialise() {
}
device->index = i;
device->sectorSize = isATAPI[i] ? ATAPI_SECTOR_SIZE : ATA_SECTOR_SIZE;
device->sectorCount = sectorCount[i];
device->information.sectorSize = isATAPI[i] ? ATAPI_SECTOR_SIZE : ATA_SECTOR_SIZE;
device->information.sectorCount = sectorCount[i];
device->maxAccessSectorCount = isATAPI[i] ? 31 : 64;
device->readOnly = isATAPI[i];
device->driveType = isATAPI[i] ? ES_DRIVE_TYPE_CDROM : ES_DRIVE_TYPE_HDD;
device->information.readOnly = isATAPI[i];
device->information.driveType = isATAPI[i] ? ES_DRIVE_TYPE_CDROM : ES_DRIVE_TYPE_HDD;
device->access = [] (KBlockDeviceAccessRequest request) {
request.dispatchGroup->Start();

View File

@ -172,8 +172,8 @@ static bool Mount(Volume *volume) {
ScanInternal(EsLiteral("ESSENCE.DAT;1"), volume->rootDirectory, &record);
record.extentSize.x = (record.extentSize.x + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (!record.length || record.extentStart.x >= volume->block->sectorCount
|| record.extentSize.x >= volume->block->sectorCount - record.extentStart.x) {
if (!record.length || record.extentStart.x >= volume->block->information.sectorCount
|| record.extentSize.x >= volume->block->information.sectorCount - record.extentStart.x) {
goto notBoot;
}
@ -205,7 +205,7 @@ static bool Mount(Volume *volume) {
KernelLog(LOG_INFO, "ISO9660", "found boot disc", "Found boot disc. Image at %d/%d.\n",
record.extentStart.x, record.extentSize.x);
FSPartitionDeviceCreate(volume->block, record.extentStart.x, record.extentSize.x, ES_FLAGS_DEFAULT, "CD-ROM boot partition");
FSPartitionDeviceCreate(volume->block, record.extentStart.x, record.extentSize.x, ES_FLAGS_DEFAULT, EsLiteral("CD-ROM boot partition"));
}
notBoot:;
@ -495,9 +495,9 @@ static void DeviceAttach(KDevice *parent) {
return;
}
if (volume->block->sectorSize != SECTOR_SIZE) {
if (volume->block->information.sectorSize != SECTOR_SIZE) {
KernelLog(LOG_ERROR, "ISO9660", "incorrect sector size", "DeviceAttach - Expected 2KB sectors, but drive's sectors are %D.\n",
volume->block->sectorSize);
volume->block->information.sectorSize);
KDeviceDestroy(volume);
return;
}

View File

@ -317,8 +317,8 @@ bool NVMeController::Access(struct NVMeDrive *drive, uint64_t offsetBytes, size_
KernelLog(LOG_VERBOSE, "NVMe", "start access", "Start access of %d, offset %D, count %D, using slot %d.\n",
drive->nsid, offsetBytes, countBytes, ioSubmissionQueueTail);
uint64_t offsetSector = offsetBytes / drive->sectorSize;
uint64_t countSectors = countBytes / drive->sectorSize;
uint64_t offsetSector = offsetBytes / drive->information.sectorSize;
uint64_t countSectors = countBytes / drive->information.sectorSize;
// Build the PRP list.
@ -801,11 +801,11 @@ void NVMeController::Initialise() {
device->controller = this;
device->nsid = nsid;
device->sectorSize = sectorBytes;
device->sectorCount = capacity / sectorBytes;
device->information.sectorSize = sectorBytes;
device->information.sectorCount = capacity / sectorBytes;
device->maxAccessSectorCount = maximumDataTransferBytes / sectorBytes;
device->readOnly = readOnly;
device->driveType = ES_DRIVE_TYPE_SSD;
device->information.readOnly = readOnly;
device->information.driveType = ES_DRIVE_TYPE_SSD;
device->access = [] (KBlockDeviceAccessRequest request) {
NVMeDrive *drive = (NVMeDrive *) request.device;

View File

@ -98,8 +98,8 @@ void DriveAccess(KBlockDeviceAccessRequest request) {
Device *device = drive->device;
request.dispatchGroup->Start();
uint32_t offsetSectors = request.offset / drive->sectorSize;
uint32_t countSectors = request.count / drive->sectorSize;
uint32_t offsetSectors = request.offset / drive->information.sectorSize;
uint32_t countSectors = request.count / drive->information.sectorSize;
CommandBlock command = {
.transferBytes = (uint32_t) request.count,
@ -194,12 +194,12 @@ void Device::Initialise() {
drive->device = this;
drive->lun = i;
drive->sectorSize = sectorBytes;
drive->sectorCount = sectorCount;
drive->information.sectorSize = sectorBytes;
drive->information.sectorCount = sectorCount;
drive->maxAccessSectorCount = 262144 / sectorBytes; // TODO How to determine this? What does the USB layer support?
drive->readOnly = false; // TODO How to detect this?
drive->information.readOnly = false; // TODO How to detect this?
drive->access = DriveAccess;
drive->driveType = ES_DRIVE_TYPE_USB_MASS_STORAGE;
drive->information.driveType = ES_DRIVE_TYPE_USB_MASS_STORAGE;
FSRegisterBlockDevice(drive);
}

View File

@ -135,6 +135,7 @@ void KDeviceSendConnectedMessage(KDevice *device, EsDeviceType type) {
}
device->flags |= K_DEVICE_VISIBLE_TO_USER;
device->type = type;
KMutexRelease(&deviceTreeMutex);

View File

@ -1546,16 +1546,16 @@ bool FSBlockDeviceAccess(KBlockDeviceAccessRequest request) {
return true;
}
if (device->readOnly && request.operation == K_ACCESS_WRITE) {
if (device->information.readOnly && request.operation == K_ACCESS_WRITE) {
KernelPanic("FSBlockDeviceAccess - Drive %x is read-only.\n", device);
}
if (request.offset / device->sectorSize > device->sectorCount
|| (request.offset + request.count) / device->sectorSize > device->sectorCount) {
if (request.offset / device->information.sectorSize > device->information.sectorCount
|| (request.offset + request.count) / device->information.sectorSize > device->information.sectorCount) {
KernelPanic("FSBlockDeviceAccess - Access out of bounds on drive %x.\n", device);
}
if ((request.offset % device->sectorSize) || (request.count % device->sectorSize)) {
if ((request.offset % device->information.sectorSize) || (request.count % device->information.sectorSize)) {
KernelPanic("FSBlockDeviceAccess - Misaligned access.\n");
}
@ -1581,7 +1581,7 @@ bool FSBlockDeviceAccess(KBlockDeviceAccessRequest request) {
r.offset = request.offset;
while (request.count) {
r.count = device->maxAccessSectorCount * device->sectorSize;
r.count = device->maxAccessSectorCount * device->information.sectorSize;
if (r.count > request.count) r.count = request.count;
buffer.offsetBytes = 0;
buffer.totalByteCount = r.count;
@ -1669,25 +1669,28 @@ struct PartitionDevice : KBlockDevice {
void FSPartitionDeviceAccess(KBlockDeviceAccessRequest request) {
PartitionDevice *_device = (PartitionDevice *) request.device;
request.device = (KBlockDevice *) _device->parent;
request.offset += _device->sectorOffset * _device->sectorSize;
request.offset += _device->sectorOffset * _device->information.sectorSize;
FSBlockDeviceAccess(request);
}
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *cName) {
PartitionDevice *child = (PartitionDevice *) KDeviceCreate(cName, parent, sizeof(PartitionDevice));
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *model, size_t modelBytes) {
PartitionDevice *child = (PartitionDevice *) KDeviceCreate("Partition", parent, sizeof(PartitionDevice));
if (!child) return;
if (modelBytes > sizeof(child->information.model)) modelBytes = sizeof(child->information.model);
EsMemoryCopy(child->information.model, model, modelBytes);
child->parent = parent;
child->sectorSize = parent->sectorSize;
child->information.sectorSize = parent->information.sectorSize;
child->maxAccessSectorCount = parent->maxAccessSectorCount;
child->sectorOffset = offset;
child->sectorCount = sectorCount;
child->noMBR = flags & FS_PARTITION_DEVICE_NO_MBR ? true : false;
child->readOnly = parent->readOnly;
child->information.sectorCount = sectorCount;
child->information.noMBR = flags & FS_PARTITION_DEVICE_NO_MBR ? true : false;
child->information.readOnly = parent->information.readOnly;
child->access = FSPartitionDeviceAccess;
child->cModel = cName;
child->nestLevel = parent->nestLevel + 1;
child->driveType = parent->driveType;
child->information.modelBytes = modelBytes;
child->information.nestLevel = parent->information.nestLevel + 1;
child->information.driveType = parent->information.driveType;
FSRegisterBlockDevice(child);
}
@ -1697,7 +1700,7 @@ void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOf
//////////////////////////////////////////
bool FSSignatureCheck(KInstalledDriver *driver, KDevice *device) {
uint8_t *block = ((KBlockDevice *) device)->information;
uint8_t *block = ((KBlockDevice *) device)->signatureBlock;
EsINIState s = {};
s.buffer = driver->config;
@ -1723,7 +1726,7 @@ bool FSSignatureCheck(KInstalledDriver *driver, KDevice *device) {
}
bool FSCheckMBR(KBlockDevice *device) {
if (device->information[510] != 0x55 || device->information[511] != 0xAA) {
if (device->signatureBlock[510] != 0x55 || device->signatureBlock[511] != 0xAA) {
return false;
}
@ -1733,23 +1736,23 @@ bool FSCheckMBR(KBlockDevice *device) {
bool present[4] = {};
for (uintptr_t i = 0; i < 4; i++) {
if (!device->information[4 + 0x1BE + i * 0x10]) {
if (!device->signatureBlock[4 + 0x1BE + i * 0x10]) {
continue;
}
offsets[i] =
((uint32_t) device->information[0x1BE + i * 0x10 + 8 ] << 0 )
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 9 ] << 8 )
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 10] << 16)
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 11] << 24);
((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 8 ] << 0 )
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 9 ] << 8 )
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 10] << 16)
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 11] << 24);
counts[i] =
((uint32_t) device->information[0x1BE + i * 0x10 + 12] << 0 )
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 13] << 8 )
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 14] << 16)
+ ((uint32_t) device->information[0x1BE + i * 0x10 + 15] << 24);
((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 12] << 0 )
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 13] << 8 )
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 14] << 16)
+ ((uint32_t) device->signatureBlock[0x1BE + i * 0x10 + 15] << 24);
present[i] = true;
if (offsets[i] > device->sectorCount || counts[i] > device->sectorCount - offsets[i] || counts[i] < 32) {
if (offsets[i] > device->information.sectorCount || counts[i] > device->information.sectorCount - offsets[i] || counts[i] < 32) {
KernelLog(LOG_INFO, "FS", "invalid MBR", "Partition %d has offset %d and count %d, which is invalid. Ignoring the rest of the MBR...\n",
i, offsets[i], counts[i]);
return false;
@ -1760,7 +1763,7 @@ bool FSCheckMBR(KBlockDevice *device) {
if (present[i]) {
KernelLog(LOG_INFO, "FS", "MBR partition", "Found MBR partition %d with offset %d and count %d.\n",
i, offsets[i], counts[i]);
FSPartitionDeviceCreate(device, offsets[i], counts[i], FS_PARTITION_DEVICE_NO_MBR, "MBR partition");
FSPartitionDeviceCreate(device, offsets[i], counts[i], FS_PARTITION_DEVICE_NO_MBR, EsLiteral("MBR partition"));
}
}
@ -1790,31 +1793,31 @@ bool FSFileSystemInitialise(KFileSystem *fileSystem) {
}
void FSDetectFileSystem(KBlockDevice *device) {
KernelLog(LOG_INFO, "FS", "detect file system", "Detecting file system on block device '%z'.\n", device->cModel);
KernelLog(LOG_INFO, "FS", "detect file system", "Detecting file system on block device '%s'.\n", device->information.modelBytes, device->information.model);
if (device->nestLevel > 4) {
if (device->information.nestLevel > 4) {
KernelLog(LOG_ERROR, "FS", "file system nest limit", "Reached file system nest limit (4), ignoring device.\n");
}
uint64_t sectorsToRead = (K_SIGNATURE_BLOCK_SIZE + device->sectorSize - 1) / device->sectorSize;
uint64_t sectorsToRead = (K_SIGNATURE_BLOCK_SIZE + device->information.sectorSize - 1) / device->information.sectorSize;
if (sectorsToRead > device->sectorCount) {
if (sectorsToRead > device->information.sectorCount) {
KernelLog(LOG_ERROR, "FS", "drive too small", "The drive must be at least %D (K_SIGNATURE_BLOCK_SIZE).\n", K_SIGNATURE_BLOCK_SIZE);
return;
}
uint8_t *information = (uint8_t *) EsHeapAllocate(sectorsToRead * device->sectorSize, false, K_FIXED);
uint8_t *signatureBlock = (uint8_t *) EsHeapAllocate(sectorsToRead * device->information.sectorSize, false, K_FIXED);
if (!information) {
if (!signatureBlock) {
return;
}
device->information = information;
device->signatureBlock = signatureBlock;
KDMABuffer dmaBuffer = { (uintptr_t) information };
KDMABuffer dmaBuffer = { (uintptr_t) signatureBlock };
KBlockDeviceAccessRequest request = {};
request.device = device;
request.count = sectorsToRead * device->sectorSize;
request.count = sectorsToRead * device->information.sectorSize;
request.operation = K_ACCESS_READ;
request.buffer = &dmaBuffer;
@ -1822,14 +1825,14 @@ void FSDetectFileSystem(KBlockDevice *device) {
// We could not access the block device.
KernelLog(LOG_ERROR, "FS", "detect fileSystem read failure", "The signature block could not be read on block device %x.\n", device);
} else {
if (!device->noMBR && FSCheckMBR(device)) {
if (!device->information.noMBR && FSCheckMBR(device)) {
// Found an MBR.
} else {
KDeviceAttach(device, "Files", FSSignatureCheck);
}
}
EsHeapFree(information, sectorsToRead * device->sectorSize, K_FIXED);
EsHeapFree(signatureBlock, sectorsToRead * device->information.sectorSize, K_FIXED);
KDeviceCloseHandle(device);
}

View File

@ -551,6 +551,7 @@ struct KDevice {
#define K_DEVICE_VISIBLE_TO_USER (1 << 1) // A ES_MSG_DEVICE_CONNECTED message was sent to Desktop for this device.
uint8_t flags;
uint32_t handles;
EsDeviceType type;
EsObjectID objectID;
// These callbacks are called with the deviceTreeMutex locked, and are all optional.
@ -628,21 +629,16 @@ typedef void (*KDeviceAccessCallbackFunction)(KBlockDeviceAccessRequest request)
struct KBlockDevice : KDevice {
KDeviceAccessCallbackFunction access; // Don't call directly; see KFileSystem::Access.
size_t sectorSize, maxAccessSectorCount;
EsFileOffset sectorCount;
bool noMBR; // Set to `true` if this device cannot contain a MBR.
bool readOnly;
uint8_t nestLevel;
uint8_t driveType;
const char *cModel;
EsBlockDeviceInformation information;
size_t maxAccessSectorCount;
K_PRIVATE
uint8_t *information; // Signature block. Only valid during fileSystem detection.
uint8_t *signatureBlock; // Signature block. Only valid during fileSystem detection.
};
#define FS_PARTITION_DEVICE_NO_MBR (1 << 0)
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *cName);
void FSPartitionDeviceCreate(KBlockDevice *parent, EsFileOffset offset, EsFileOffset sectorCount, unsigned flags, const char *name, size_t nameBytes);
// ---------------------------------------------------------------------------------------------------------------
// PCI.

View File

@ -725,9 +725,14 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_MAP_OBJECT) {
SYSCALL_IMPLEMENT(ES_SYSCALL_CONSTANT_BUFFER_CREATE) {
if (argument2 > SYSCALL_BUFFER_LIMIT) SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
SYSCALL_BUFFER(argument0, argument2, 1, false);
SYSCALL_HANDLE(argument1, KERNEL_OBJECT_PROCESS, process, Process);
SYSCALL_RETURN(MakeConstantBuffer((void *) argument0, argument2, process), false);
if (argument2) {
SYSCALL_BUFFER(argument0, argument2, 1, false);
SYSCALL_RETURN(MakeConstantBuffer((void *) argument0, argument2, process), false);
} else {
SYSCALL_RETURN(MakeConstantBuffer(nullptr, 0, process), false);
}
}
SYSCALL_IMPLEMENT(ES_SYSCALL_HANDLE_SHARE) {
@ -748,7 +753,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {
EsMemoryZero(&information, sizeof(EsVolumeInformation));
EsMemoryCopy(information.label, fileSystem->name, sizeof(fileSystem->name));
information.labelBytes = fileSystem->nameBytes;
information.driveType = fileSystem->block->driveType;
information.driveType = fileSystem->block->information.driveType;
information.spaceUsed = fileSystem->spaceUsed;
information.spaceTotal = fileSystem->spaceTotal;
information.id = fileSystem->objectID;
@ -1816,6 +1821,24 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_CONNECTION_NOTIFY) {
SYSCALL_RETURN(ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_DEVICE_CONTROL) {
SYSCALL_HANDLE(argument0, KERNEL_OBJECT_DEVICE, device, KDevice);
if (device->type == ES_DEVICE_BLOCK) {
KBlockDevice *block = (KBlockDevice *) device;
if (argument1 == ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION) {
SYSCALL_WRITE(argument3, &block->information, sizeof(EsBlockDeviceInformation));
} else {
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
}
} else {
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
}
SYSCALL_RETURN(ES_SUCCESS, false);
}
SYSCALL_IMPLEMENT(ES_SYSCALL_DEBUG_COMMAND) {
#ifdef DEBUG_BUILD
if (argument0 == 1) {

View File

@ -6,6 +6,7 @@ EsPOSIXInitialise=4
EsFileStoreReadAll=5
EsPOSIXSystemCall=6
EsINIParse=7
EsDeviceEnumerate=8
EsTakeSystemSnapshot=9
EsListViewFocusItem=10
_EsInstanceCreate=11
@ -444,3 +445,4 @@ EsColorInterpolate=443
EsBufferReadInt32Endian=444
EsBufferWriteInt32Endian=445
EsSystemGetOptimalWorkQueueThreadCount=446
EsDeviceControl=447