installation progress

This commit is contained in:
nakst 2021-09-12 18:45:34 +01:00
parent f53a980a65
commit dfd80c3dcd
24 changed files with 748 additions and 319 deletions

View File

@ -1,3 +1,6 @@
// TODO Handle crashing?
// TODO Write any modified settings during installation.
#define INSTALLER
#define ES_CRT_WITHOUT_PREFIX
@ -5,6 +8,7 @@
#include <shared/hash.cpp>
#include <shared/strings.cpp>
#include <shared/partitions.cpp>
#include <ports/lzma/LzmaDec.c>
#include <shared/array.cpp>
@ -13,12 +17,15 @@
#undef IMPLEMENTATION
#define Log(...)
#define exit(x) EsThreadTerminate(ES_CURRENT_THREAD)
// TODO Error handling.
#define exit(x) EsAssert(false)
#include <shared/esfs2.h>
// Assume an additional 64MB of storage capacity is needed on top of totalUncompressedBytes.
#define PARTITION_OVERHEAD (64 * 1024 * 1024)
#define MSG_SET_PROGRESS ((EsMessageType) (ES_MSG_USER_START + 1))
struct InstallerMetadata {
uint64_t totalUncompressedBytes;
};
@ -48,15 +55,35 @@ const EsStyle styleButtonsRow = {
},
};
const EsStyle styleCustomizeTable = {
.metrics = {
.mask = ES_THEME_METRICS_GAP_MAJOR | ES_THEME_METRICS_GAP_MINOR,
.gapMajor = 7,
.gapMinor = 7,
},
};
InstallerMetadata *metadata;
Array<EsMessageDevice> connectedDrives;
EsListView *drivesList;
EsPanel *driveInformation;
EsObjectID selectedDriveID;
EsButton *installButton;
EsButton *finishButton;
EsPanel *switcher;
EsPanel *panelInstallOptions;
EsPanel *panelCustomizeOptions;
EsPanel *panelLicenses;
EsPanel *panelWait;
EsPanel *panelComplete;
EsTextbox *userNameTextbox;
EsTextDisplay *progressDisplay;
const char *cSelectedFont;
uint8_t progress;
bool onWaitScreen, startedInstallation;
EsBlockDeviceInformation blockDeviceInformation;
EsHandle driveHandle;
EsFileOffset partitionOffset;
/////////////////////////////////////////////
@ -128,6 +155,8 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
e->inFileOffset = sizeof(header);
uint64_t crc64 = 0, actualCRC64 = 0;
uint64_t totalBytesExtracted = 0;
uint8_t lastProgressByte = 0;
EsMemoryCopy(e->pathBuffer, pathOut, pathOutBytes);
@ -155,7 +184,17 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
Decompress(e, e->copyBuffer, copyBytes);
EsFileWriteSync(fileOut.handle, fileOutPosition, copyBytes, e->copyBuffer);
fileOutPosition += copyBytes;
totalBytesExtracted += copyBytes;
crc64 = CalculateCRC64(e->copyBuffer, copyBytes, crc64);
EsMessage m = { MSG_SET_PROGRESS };
double progress = (double) totalBytesExtracted / metadata->totalUncompressedBytes;
m.user.context1.u = 10 + 80 * progress;
if (lastProgressByte != m.user.context1.u) {
lastProgressByte = m.user.context1.u;
EsMessagePost(nullptr, &m);
}
}
EsHandleClose(fileOut.handle);
@ -169,23 +208,68 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
/////////////////////////////////////////////
void ReadBlock(uint64_t, uint64_t, void *) {
// TODO.
// TODO Error handling.
uint64_t writeOffset;
uint64_t writeBytes;
uint8_t writeBuffer[BUFFER_SIZE];
void FlushWriteBuffer() {
if (!writeBytes) return;
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + writeOffset, writeBytes };
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, writeBuffer, parameters);
EsAssert(error == ES_SUCCESS);
writeBytes = 0;
}
void WriteBlock(uint64_t, uint64_t, void *) {
// TODO.
void ReadBlock(uint64_t block, uint64_t count, void *buffer) {
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + block * blockSize, count * blockSize };
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_READ, buffer, parameters);
EsAssert(error == ES_SUCCESS);
}
void WriteBytes(uint64_t, uint64_t, void *) {
// TODO.
void WriteBlock(uint64_t block, uint64_t count, void *buffer) {
uint64_t offset = block * blockSize, bytes = count * blockSize;
if (writeBytes && writeOffset + writeBytes == offset && writeBytes + bytes < sizeof(writeBuffer)) {
EsMemoryCopy(writeBuffer + writeBytes, buffer, bytes);
writeBytes += bytes;
} else {
FlushWriteBuffer();
writeOffset = offset;
writeBytes = bytes;
EsMemoryCopy(writeBuffer, buffer, bytes);
}
}
void WriteBytes(uint64_t byteOffset, uint64_t byteCount, void *buffer) {
uint64_t firstSector = byteOffset / blockDeviceInformation.sectorSize;
uint64_t lastSector = (byteOffset + byteCount - 1) / blockDeviceInformation.sectorSize;
uint64_t sectorCount = lastSector - firstSector + 1;
void *buffer2 = EsHeapAllocate(sectorCount * blockDeviceInformation.sectorSize, false);
for (uintptr_t i = 0; i < sectorCount; i++) {
if (i > 0 && i < sectorCount - 1) continue;
EsFileOffset parameters[2] = { (partitionOffset + firstSector + i) * blockDeviceInformation.sectorSize, blockDeviceInformation.sectorSize } ;
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_READ, (uint8_t *) buffer2 + i * blockDeviceInformation.sectorSize, parameters);
EsAssert(error == ES_SUCCESS);
}
EsMemoryCopy((uint8_t *) buffer2 + byteOffset % blockDeviceInformation.sectorSize, buffer, byteCount);
EsFileOffset parameters[2] = { (partitionOffset + firstSector) * blockDeviceInformation.sectorSize, sectorCount * blockDeviceInformation.sectorSize };
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, buffer, parameters);
EsAssert(error == ES_SUCCESS);
EsHeapFree(buffer2);
}
/////////////////////////////////////////////
EsBlockDeviceInformation ConnectedDriveGetInformation(EsHandle handle) {
EsBlockDeviceInformation information;
EsDeviceControl(handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, 0, &information);
EsDeviceControl(handle, ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION, &information, nullptr);
for (uintptr_t i = 0; i < information.modelBytes; i++) {
if (information.model[i] == 0) {
@ -245,6 +329,7 @@ void ConnectedDriveSelect(uintptr_t index) {
EsElementSetDisabled(installButton, true);
EsBlockDeviceInformation information = ConnectedDriveGetInformation(device.handle);
EsElementStartTransition(driveInformation, ES_TRANSITION_FADE_VIA_TRANSPARENT, ES_FLAGS_DEFAULT, 4.0f);
EsElementDestroyContents(driveInformation);
EsPanel *nameRow = EsPanelCreate(driveInformation, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
@ -257,20 +342,49 @@ void ConnectedDriveSelect(uintptr_t index) {
EsIconDisplay *statusIcon = EsIconDisplayCreate(messageRow, ES_CELL_V_TOP, ES_STYLE_ICON_DISPLAY_SMALL, ES_ICON_DIALOG_INFORMATION);
EsSpacerCreate(messageRow, ES_CELL_V_FILL, 0, 8, 0);
// TODO Check there are no file systems already on the drive.
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(information.sectorSize, false);
EsFileOffset parameters[2] = { 0, information.sectorSize };
EsError readError = EsDeviceControl(device.handle, ES_DEVICE_CONTROL_BLOCK_READ, sectorBuffer, parameters);
bool alreadyHasPartitions = false;
bool showCapacity = true;
if (readError == ES_SUCCESS && information.sectorSize >= 0x200) {
// TODO Support GPT.
MBRPartition partitions[4];
if (information.readOnly) {
if (MBRGetPartitions(sectorBuffer, information.sectorCount, partitions)) {
for (uintptr_t i = 0; i < 4; i++) {
if (partitions[i].present) {
alreadyHasPartitions = true;
}
}
}
}
EsHeapFree(sectorBuffer);
bool showCapacity = false;
if (information.sectorSize != 0x200) {
// TODO Allow other sector sizes if a GPT is being used.
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveUnsupported));
} else if (readError != ES_SUCCESS) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveCouldNotRead));
} else if (information.readOnly) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveReadOnly));
showCapacity = false;
} else if (alreadyHasPartitions) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveAlreadyHasPartitions));
} else if (information.sectorSize * information.sectorCount < metadata->totalUncompressedBytes + PARTITION_OVERHEAD) {
EsIconDisplaySetIcon(statusIcon, ES_ICON_DIALOG_ERROR);
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveNotEnoughSpace));
showCapacity = true;
} else {
EsTextDisplayCreate(messageRow, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDriveOkay));
EsElementSetDisabled(installButton, false);
showCapacity = true;
}
if (showCapacity) {
@ -286,6 +400,159 @@ void ConnectedDriveSelect(uintptr_t index) {
/////////////////////////////////////////////
EsError Install() {
EsMessage m = { MSG_SET_PROGRESS };
EsError error;
size_t mbrBytes, stage1Bytes, stage2Bytes, kernelBytes;
void *mbr = EsFileReadAll(EsLiteral("0:/mbr.dat"), &mbrBytes);
void *stage1 = EsFileReadAll(EsLiteral("0:/stage1.dat"), &stage1Bytes);
void *stage2 = EsFileReadAll(EsLiteral("0:/stage2.dat"), &stage2Bytes);
EsMessageDevice drive = {};
for (uintptr_t i = 0; i < connectedDrives.Length(); i++) {
if (connectedDrives[i].id == selectedDriveID) {
drive = connectedDrives[i];
}
}
EsAssert(drive.handle);
EsBlockDeviceInformation driveInformation = ConnectedDriveGetInformation(drive.handle);
blockDeviceInformation = driveInformation;
driveHandle = drive.handle;
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(driveInformation.sectorSize, false);
if (!sectorBuffer) return ES_ERROR_INSUFFICIENT_RESOURCES;
size_t bootloaderSectors = (stage1Bytes + stage2Bytes + driveInformation.sectorSize - 1) / driveInformation.sectorSize;
uint8_t *bootloader = (uint8_t *) EsHeapAllocate(bootloaderSectors * driveInformation.sectorSize, true);
EsMemoryCopy(bootloader, stage1, stage1Bytes);
EsMemoryCopy(bootloader + stage1Bytes, stage2, stage2Bytes);
m.user.context1.u = 1;
EsMessagePost(nullptr, &m);
// Create the partition table.
// TODO GPT.
// TODO Adding new entries to existing tables.
EsAssert(driveInformation.sectorSize == 0x200);
partitionOffset = 0x800;
EsFileOffset partitionBytes = driveInformation.sectorSize * (driveInformation.sectorCount - partitionOffset);
uint32_t partitions[16] = { 0x80 /* bootable */, 0x83 /* type */ };
uint16_t bootSignature = 0xAA55;
partitions[2] = partitionOffset; // Offset.
partitions[3] = driveInformation.sectorCount - 0x800; // Sector count.
MBRFixPartition(partitions);
EsMemoryCopy(sectorBuffer + 0, mbr, 446);
EsMemoryCopy(sectorBuffer + 446, partitions, 64);
EsMemoryCopy(sectorBuffer + 510, &bootSignature, 2);
{
EsFileOffset parameters[2] = { 0, driveInformation.sectorSize };
error = EsDeviceControl(drive.handle, ES_DEVICE_CONTROL_BLOCK_WRITE, sectorBuffer, parameters);
if (error != ES_SUCCESS) return error;
}
m.user.context1.u = 2;
EsMessagePost(nullptr, &m);
// Install the bootloader.
{
EsFileOffset parameters[2] = { partitionOffset * driveInformation.sectorSize, bootloaderSectors * driveInformation.sectorSize };
error = EsDeviceControl(drive.handle, ES_DEVICE_CONTROL_BLOCK_WRITE, bootloader, parameters);
if (error != ES_SUCCESS) return error;
}
m.user.context1.u = 4;
EsMessagePost(nullptr, &m);
// Format the partition.
void *kernel = EsFileReadAll(EsLiteral(K_OS_FOLDER "/Kernel.esx"), &kernelBytes);
m.user.context1.u = 6;
EsMessagePost(nullptr, &m);
EsUniqueIdentifier installationIdentifier;
for (int i = 0; i < 16; i++) {
installationIdentifier.d[i] = EsRandomU8();
}
Format(partitionBytes, interfaceString_InstallerVolumeLabel, installationIdentifier, kernel, kernelBytes);
FlushWriteBuffer();
m.user.context1.u = 10;
EsMessagePost(nullptr, &m);
// TODO Mount the new partition.
// Extract the archive.
// TODO Extract to the new partition.
error = Extract(EsLiteral("0:/installer_archive.dat"), EsLiteral("0:/test"));
if (error != ES_SUCCESS) return error;
return ES_SUCCESS;
}
void InstallThread(EsGeneric) {
Install();
EsMessage m = { MSG_SET_PROGRESS };
m.user.context1.u = 100;
EsMessagePost(nullptr, &m);
}
/////////////////////////////////////////////
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelLicenses, ES_TRANSITION_FADE_IN);
}
void ButtonInstallOptions(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_FADE_IN);
}
void ButtonShutdown(EsInstance *, EsElement *, EsCommand *) {
EsSyscall(ES_SYSCALL_SHUTDOWN, SHUTDOWN_ACTION_POWER_OFF, 0, 0, 0);
}
void ButtonRestart(EsInstance *, EsElement *, EsCommand *) {
EsSyscall(ES_SYSCALL_SHUTDOWN, SHUTDOWN_ACTION_RESTART, 0, 0, 0);
}
void ButtonInstall(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelCustomizeOptions, ES_TRANSITION_FADE_IN);
EsElementFocus(userNameTextbox);
startedInstallation = true;
EsThreadCreate(InstallThread, nullptr, 0);
}
void ButtonFont(EsInstance *, EsElement *element, EsCommand *) {
EsFontInformation information;
cSelectedFont = (const char *) element->userData.p;
if (EsFontDatabaseLookupByName(cSelectedFont, -1, &information)) {
_EsUISetFont(information.id);
}
}
void ButtonFinish(EsInstance *, EsElement *, EsCommand *) {
if (progress == 100) {
EsPanelSwitchTo(switcher, panelComplete, ES_TRANSITION_FADE_IN);
} else {
onWaitScreen = true;
EsPanelSwitchTo(switcher, panelWait, ES_TRANSITION_FADE_IN);
}
}
int DrivesListMessage(EsElement *element, EsMessage *message) {
if (message->type == ES_MSG_LIST_VIEW_SELECT) {
EsGeneric deviceID;
@ -303,23 +570,6 @@ int DrivesListMessage(EsElement *element, EsMessage *message) {
return 0;
}
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelLicenses, ES_TRANSITION_FADE_IN);
}
void ButtonInstallOptions(EsInstance *, EsElement *, EsCommand *) {
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_FADE_IN);
}
void ButtonShutdown(EsInstance *, EsElement *, EsCommand *) {
EsSystemShowShutdownDialog();
}
void ButtonInstall(EsInstance *, EsElement *, EsCommand *) {
// TODO.
}
int SwitcherMessage(EsElement *, EsMessage *message) {
if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) {
return EsMessageSend(panelInstallOptions, message);
@ -328,64 +578,129 @@ int SwitcherMessage(EsElement *, EsMessage *message) {
return 0;
}
int UserNameTextboxMessage(EsElement *, EsMessage *message) {
if (message->type == ES_MSG_TEXTBOX_UPDATED) {
EsElementSetEnabled(finishButton, EsTextboxGetLineLength(userNameTextbox));
}
return 0;
}
void _start() {
_init();
metadata = (InstallerMetadata *) EsFileReadAll(EsLiteral("0:/installer_metadata.dat"), nullptr);
EsAssert(metadata);
EsWindow *window = EsWindowCreate(_EsInstanceCreate(sizeof(EsInstance), nullptr), ES_WINDOW_PLAIN);
EsHandle handle = _EsWindowGetHandle(window);
window->instance->window = window;
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, handle, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0, 0, ES_WINDOW_PROPERTY_FOCUSED);
EsPanel *sheet = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
switcher = EsPanelCreate(sheet, ES_CELL_H_FILL | ES_PANEL_SWITCHER);
switcher->messageUser = SwitcherMessage;
{
EsWindow *window = EsWindowCreate(_EsInstanceCreate(sizeof(EsInstance), nullptr), ES_WINDOW_PLAIN);
EsHandle handle = EsWindowGetHandle(window);
window->instance->window = window;
panelInstallOptions = EsPanelCreate(switcher, ES_CELL_H_FILL, &styleRoot);
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_NONE);
EsTextDisplayCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
EsRectangle screen;
EsSyscall(ES_SYSCALL_SCREEN_BOUNDS_GET, 0, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_MOVE, handle, (uintptr_t) &screen, 0, 0);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, ES_WINDOW_SOLID_TRUE, 0, ES_WINDOW_PROPERTY_SOLID);
EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, handle, 0, 0, ES_WINDOW_PROPERTY_FOCUSED);
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
EsPanel *drivesSplit = EsPanelCreate(drivesPanel, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
EsPanel *drivesLeft = EsPanelCreate(drivesSplit, ES_CELL_H_FILL);
EsTextDisplayCreate(drivesLeft, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDrivesList));
EsSpacerCreate(drivesLeft, ES_CELL_H_FILL, 0, 0, 8);
drivesList = EsListViewCreate(drivesLeft, ES_CELL_H_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
drivesList->messageUser = DrivesListMessage;
EsElementFocus(drivesList);
EsSpacerCreate(drivesSplit, ES_CELL_V_FILL, 0, 25, 0);
driveInformation = EsPanelCreate(drivesSplit, ES_CELL_H_FILL | ES_CELL_V_FILL);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDrivesSelectHint));
EsPanel *sheet = EsPanelCreate(window, ES_PANEL_VERTICAL | ES_CELL_PUSH | ES_CELL_CENTER, ES_STYLE_INSTALLER_ROOT);
switcher = EsPanelCreate(sheet, ES_CELL_H_FILL | ES_PANEL_SWITCHER);
switcher->messageUser = SwitcherMessage;
EsPanel *buttonsRow = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(InstallerViewLicenses)), ButtonViewLicenses);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopShutdownAction)), ButtonShutdown);
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
installButton = EsButtonCreate(buttonsRow, ES_ELEMENT_DISABLED, 0, INTERFACE_STRING(InstallerInstall));
EsButtonOnCommand(installButton, ButtonInstall);
}
{
panelInstallOptions = EsPanelCreate(switcher, ES_CELL_H_FILL, &styleRoot);
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_NONE);
EsTextDisplayCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
{
panelLicenses = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextbox *textbox = EsTextboxCreate(panelLicenses, ES_CELL_FILL | ES_TEXTBOX_MULTILINE);
EsElementSetDisabled(textbox);
size_t bytes;
char *data = (char *) EsFileReadAll(EsLiteral("0:/installer_licenses.txt"), &bytes);
EsTextboxInsert(textbox, data, bytes);
EsHeapFree(data);
EsButtonOnCommand(EsButtonCreate(panelLicenses, ES_CELL_H_LEFT, 0, INTERFACE_STRING(InstallerGoBack)), ButtonInstallOptions);
}
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
EsPanel *drivesSplit = EsPanelCreate(drivesPanel, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
EsPanel *drivesLeft = EsPanelCreate(drivesSplit, ES_CELL_H_FILL);
EsTextDisplayCreate(drivesLeft, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerDrivesList));
EsSpacerCreate(drivesLeft, ES_CELL_H_FILL, 0, 0, 8);
drivesList = EsListViewCreate(drivesLeft, ES_CELL_H_FILL | ES_LIST_VIEW_CHOICE_SELECT | ES_LIST_VIEW_FIXED_ITEMS, ES_STYLE_LIST_CHOICE_BORDERED);
drivesList->messageUser = DrivesListMessage;
EsElementFocus(drivesList);
EsSpacerCreate(drivesSplit, ES_CELL_V_FILL, 0, 25, 0);
driveInformation = EsPanelCreate(drivesSplit, ES_CELL_H_FILL | ES_CELL_V_FILL);
EsTextDisplayCreate(driveInformation, ES_CELL_H_FILL | ES_CELL_V_FILL, &styleDrivesSelectHint, INTERFACE_STRING(InstallerDrivesSelectHint));
{
panelCustomizeOptions = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING1, INTERFACE_STRING(InstallerCustomizeOptions));
EsPanel *buttonsRow = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(InstallerViewLicenses)), ButtonViewLicenses);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopShutdownAction)), ButtonShutdown);
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
installButton = EsButtonCreate(buttonsRow, ES_ELEMENT_DISABLED, 0, INTERFACE_STRING(InstallerInstall));
EsButtonOnCommand(installButton, ButtonInstall);
EsPanel *table = EsPanelCreate(panelCustomizeOptions, ES_CELL_H_CENTER | ES_PANEL_HORIZONTAL | ES_PANEL_TABLE, &styleCustomizeTable);
EsPanelSetBands(table, 2 /* columns */);
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, ES_STYLE_TEXT_LABEL, INTERFACE_STRING(InstallerUserName));
userNameTextbox = EsTextboxCreate(table, ES_CELL_H_LEFT);
userNameTextbox->messageUser = UserNameTextboxMessage;
EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_V_TOP, ES_STYLE_TEXT_RADIO_GROUP_LABEL, INTERFACE_STRING(InstallerSystemFont));
EsPanel *fonts = EsPanelCreate(table, ES_CELL_H_LEFT);
EsButton *button = EsButtonCreate(fonts, ES_BUTTON_RADIOBOX | ES_CELL_H_EXPAND, 0, INTERFACE_STRING(InstallerFontDefault));
button->userData = (void *) "Inter";
EsButtonOnCommand(button, ButtonFont);
EsButtonSetCheck(button, ES_CHECK_CHECKED);
button = EsButtonCreate(fonts, ES_BUTTON_RADIOBOX | ES_CELL_H_EXPAND, 0, EsLiteral("Atkinson Hyperlegible"));
button->userData = (void *) "Atkinson Hyperlegible";
EsButtonOnCommand(button, ButtonFont);
button = EsButtonCreate(fonts, ES_BUTTON_RADIOBOX | ES_CELL_H_EXPAND, 0, EsLiteral("OpenDyslexic"));
button->userData = (void *) "OpenDyslexic";
EsButtonOnCommand(button, ButtonFont);
EsTextDisplayCreate(panelCustomizeOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH_SECONDARY, INTERFACE_STRING(InstallerCustomizeOptionsHint));
EsSpacerCreate(panelCustomizeOptions, ES_CELL_FILL);
EsPanel *buttonsRow = EsPanelCreate(panelCustomizeOptions, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
finishButton = EsButtonCreate(buttonsRow, ES_ELEMENT_DISABLED, 0, INTERFACE_STRING(InstallerFinish));
EsButtonOnCommand(finishButton, ButtonFinish);
}
{
panelWait = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextDisplayCreate(panelWait, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
progressDisplay = EsTextDisplayCreate(panelWait, ES_TEXT_DISPLAY_RICH_TEXT | ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH);
}
{
panelComplete = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextDisplayCreate(panelComplete, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
EsVolumeInformation information;
if (EsMountPointGetVolumeInformation(EsLiteral("0:/"), &information) && information.driveType == ES_DRIVE_TYPE_USB_MASS_STORAGE) {
EsTextDisplayCreate(panelComplete, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerCompleteFromUSB));
} else {
EsTextDisplayCreate(panelComplete, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerCompleteFromOther));
}
{
panelLicenses = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
EsTextbox *textbox = EsTextboxCreate(panelLicenses, ES_CELL_FILL | ES_TEXTBOX_MULTILINE);
EsElementSetDisabled(textbox);
size_t bytes;
char *data = (char *) EsFileReadAll(EsLiteral("0:/installer_licenses.txt"), &bytes);
EsTextboxInsert(textbox, data, bytes);
EsHeapFree(data);
EsButtonOnCommand(EsButtonCreate(panelLicenses, ES_CELL_H_LEFT, 0, INTERFACE_STRING(InstallerGoBack)), ButtonInstallOptions);
}
// TODO Failure messages.
// EsWindowCreate(instance, ES_WINDOW_INSPECTOR);
EsSpacerCreate(panelComplete, ES_CELL_FILL);
EsPanel *buttonsRow = EsPanelCreate(panelComplete, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopRestartAction)), ButtonRestart);
}
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
@ -396,9 +711,27 @@ void _start() {
EsMessage *message = EsMessageReceive();
if (message->type == ES_MSG_DEVICE_CONNECTED) {
ConnectedDriveAdd(message->device);
if (!startedInstallation) {
ConnectedDriveAdd(message->device);
}
} else if (message->type == ES_MSG_DEVICE_DISCONNECTED) {
ConnectedDriveRemove(message->device);
if (!startedInstallation) {
ConnectedDriveRemove(message->device);
}
} else if (message->type == MSG_SET_PROGRESS) {
if (progress != message->user.context1.u) {
char buffer[128];
progress = message->user.context1.u;
EsAssert(progress <= 100);
size_t bytes = EsStringFormat(buffer, sizeof(buffer), "%z%d%z",
interfaceString_InstallerProgressMessage, progress, interfaceString_CommonUnitPercent);
EsTextDisplaySetContents(progressDisplay, buffer, bytes);
if (onWaitScreen && progress == 100) {
onWaitScreen = false;
EsPanelSwitchTo(switcher, panelComplete, ES_TRANSITION_FADE_IN);
}
}
}
}
}

View File

@ -489,7 +489,9 @@ WindowTab *WindowTabMoveToNewContainer(WindowTab *tab, ContainerWindow *containe
}
int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
if (message->type == ES_MSG_KEY_DOWN) {
if (desktop.installationState) {
// Do not process global keyboard shortcuts if the installer is running.
} else if (message->type == ES_MSG_KEY_DOWN) {
bool ctrlOnly = message->keyboard.modifiers == ES_MODIFIER_CTRL;
int scancode = message->keyboard.scancode;
@ -1256,6 +1258,10 @@ bool ApplicationInstanceStart(int64_t applicationID, EsApplicationStartupInforma
handleModeDuplicateList.Add(0);
}
if (application->permissions & APPLICATION_PERMISSION_SHUTDOWN) {
arguments.permissions |= ES_PERMISSION_SHUTDOWN;
}
if (application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
initialMountPoints.Add(api.mountPoints[i]);

View File

@ -1252,7 +1252,9 @@ EsRectangle UIGetTransitionEffectRectangle(EsRectangle bounds, EsTransitionType
int width = Width(bounds), height = Height(bounds);
double ratio = (double) height / (double) width;
if (!to) {
if (type == ES_TRANSITION_FADE_IN || type == ES_TRANSITION_FADE_OUT || type == ES_TRANSITION_FADE_VIA_TRANSPARENT) {
return bounds;
} else if (!to) {
if (type == ES_TRANSITION_SLIDE_UP) {
return ES_RECT_4(bounds.l, bounds.r,
bounds.t - progress * height / 2, bounds.b - progress * height / 2);
@ -1283,8 +1285,6 @@ EsRectangle UIGetTransitionEffectRectangle(EsRectangle bounds, EsTransitionType
} else if (type == ES_TRANSITION_ZOOM_IN_LIGHT) {
return ES_RECT_4(bounds.l - 5 * progress, bounds.r + 5 * progress,
bounds.t - 5 * progress * ratio, bounds.b + 5 * progress * ratio);
} else if (type == ES_TRANSITION_FADE_IN || type == ES_TRANSITION_FADE_OUT) {
return bounds;
} else if (type == ES_TRANSITION_SLIDE_UP_OVER) {
return ES_RECT_4(bounds.l, bounds.r,
bounds.t - progress * height / 4, bounds.b - progress * height / 4);
@ -1329,8 +1329,6 @@ EsRectangle UIGetTransitionEffectRectangle(EsRectangle bounds, EsTransitionType
} else if (type == ES_TRANSITION_ZOOM_IN_LIGHT) {
return ES_RECT_4(bounds.l + 5 * (1 - progress), bounds.r - 5 * (1 - progress) + 0.5,
bounds.t + 5 * (1 - progress) * ratio, bounds.b - 5 * (1 - progress) * ratio + 0.5);
} else if (type == ES_TRANSITION_FADE_IN || type == ES_TRANSITION_FADE_OUT) {
return bounds;
} else if (type == ES_TRANSITION_SLIDE_UP_OVER) {
return ES_RECT_4(bounds.l, bounds.r,
bounds.t + (1 - progress) * height / 2, bounds.b + (1 - progress) * height / 2);
@ -1355,6 +1353,14 @@ void UIDrawTransitionEffect(EsPainter *painter, EsPaintTarget *sourceSurface, Es
return;
}
if (type == ES_TRANSITION_FADE_VIA_TRANSPARENT) {
if (to) {
progress = ClampDouble(0.0, 1.0, progress * 2.0 - 1.0);
} else {
progress = ClampDouble(0.0, 1.0, progress * 2.0);
}
}
EsRectangle destinationRegion = UIGetTransitionEffectRectangle(bounds, type, progress, to);
EsRectangle sourceRegion = ES_RECT_4(0, bounds.r - bounds.l, 0, bounds.b - bounds.t);
uint16_t alpha = (to ? progress : (1 - progress)) * 255;
@ -5466,7 +5472,7 @@ void EsWindowSetTitle(EsWindow *window, const char *title, ptrdiff_t titleBytes)
MessageDesktop(buffer, bytes, window->handle);
}
EsHandle EsWindowGetHandle(EsWindow *window) {
EsHandle _EsWindowGetHandle(EsWindow *window) {
return window->handle;
}
@ -5958,6 +5964,7 @@ void UIScaleChanged(EsElement *element, EsMessage *message) {
EsMessageMutexCheck();
element->RefreshStyle(nullptr, false, true);
element->state |= UI_STATE_RELAYOUT | UI_STATE_RELAYOUT_CHILD;
EsMessageSend(element, message);
for (uintptr_t i = 0; i < element->children.Length(); i++) {
@ -5965,6 +5972,16 @@ void UIScaleChanged(EsElement *element, EsMessage *message) {
}
}
void _EsUISetFont(EsFontFamily id) {
fontManagement.sans = id;
EsMessage m = { ES_MSG_UI_SCALE_CHANGED };
for (uintptr_t i = 0; i < gui.allWindows.Length(); i++) {
UIScaleChanged(gui.allWindows[i], &m);
UIWindowNeedsUpdate(gui.allWindows[i]);
}
}
void UIMaybeRefreshStyleAll(EsElement *element) {
element->MaybeRefreshStyle();

View File

@ -329,6 +329,8 @@ define ES_ERROR_ILLEGAL_PATH (-69)
define ES_ERROR_NODE_NOT_LOADED (-71)
define ES_ERROR_DIRECTORY_ENTRY_BEING_REMOVED (-72)
define ES_ERROR_CANCELLED (-73)
define ES_ERROR_BLOCK_ACCESS_INVALID (-74)
define ES_ERROR_DEVICE_REMOVED (-75)
define ES_INVALID_HANDLE ((EsHandle) (0))
define ES_CURRENT_THREAD ((EsHandle) (0x10))
@ -1090,6 +1092,7 @@ enum EsTransitionType {
ES_TRANSITION_REVEAL_DOWN
ES_TRANSITION_FADE_IN
ES_TRANSITION_FADE_OUT
ES_TRANSITION_FADE_VIA_TRANSPARENT
ES_TRANSITION_SLIDE_UP_OVER
ES_TRANSITION_SLIDE_DOWN_OVER
ES_TRANSITION_SLIDE_UP_UNDER
@ -1128,7 +1131,9 @@ enum EsClipboardFormat {
}
enum EsDeviceControlType {
ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION
ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION = 0x1001
ES_DEVICE_CONTROL_BLOCK_READ = 0x1002
ES_DEVICE_CONTROL_BLOCK_WRITE = 0x1003
}
function_pointer int EsUICallback(struct EsElement *element, struct EsMessage *message);
@ -1965,7 +1970,7 @@ function void EsMountPointEnumerate(EsMountPointEnumerationCallback callback, Es
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);
function EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, void *dp, void *dq);
// Processes and threads.
@ -2109,6 +2114,7 @@ function void EsRichTextParse(const char *inString, ptrdiff_t inStringBytes,
EsTextStyle *baseStyle);
function void EsFontDatabaseEnumerate(EsFontEnumerationCallback callback, EsGeneric context);
function bool EsFontDatabaseLookupByName(STRING name, EsFontInformation *information); // Returns false if the font does not exist in the database.
function bool EsFontDatabaseLookupByID(EsFontFamily id, EsFontInformation *information); // Returns false if the font does not exist in the database.
function EsFontFamily EsFontDatabaseInsertFile(const EsFontInformation *information, EsFileStore *store); // Don't set the `id` field in EsFontInformation. The assigned ID will be returned. If nameBytes is 0, then the system will not try to match it with an existing font family. Set the corresponding bit in availableWeightsNormal/availableWeightsItalic for the file being added. The request is ignored if the specific variant is already in the database.
@ -2336,7 +2342,6 @@ function void EsWindowSwitchToolbar(EsWindow *window, EsElement *toolbar, EsTran
function void EsWindowSetIcon(EsWindow *window, uint32_t iconID);
function void EsWindowSetTitle(EsWindow *window, STRING title = BLANK_STRING);
function void EsWindowAddSizeAlternative(EsWindow *window, EsElement *small, EsElement *big, int widthThreshold, int heightThreshold); // Switch between elements when the window size goes below a threshold.
function EsHandle EsWindowGetHandle(EsWindow *window); // For internal use only.
function EsMenu *EsMenuCreate(EsElement *source, uint64_t flags = ES_FLAGS_DEFAULT);
function EsElement *EsMenuGetSource(EsMenu *menu); // TODO Public property?
@ -2354,6 +2359,10 @@ function EsElement *EsDialogShowAlert(EsWindow *window, STRING title, STRING con
function void EsToolbarAddFileMenu(EsElement *element, const EsFileMenuSettings *settings = ES_NULL);
// For internal use only.
function EsHandle _EsWindowGetHandle(EsWindow *window);
function void _EsUISetFont(EsFontFamily id);
// Buttons.
function EsButton *EsButtonCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL, STRING label = BLANK_STRING);

View File

@ -243,7 +243,7 @@ ES_EXTERN_C void _start();
// --------- Internal APIs:
#if defined(ES_API) || defined(KERNEL)
#if defined(ES_API) || defined(KERNEL) || defined(INSTALLER)
struct _EsPOSIXSyscall {
intptr_t index;

View File

@ -106,6 +106,7 @@ define ES_STYLE_TEXT_LABEL_INVERTED (ES_STYLE_CAST(1393))
define ES_STYLE_TEXT_LABEL_SECONDARY (ES_STYLE_CAST(1395))
define ES_STYLE_TEXT_PARAGRAPH (ES_STYLE_CAST(1397))
define ES_STYLE_TEXT_PARAGRAPH_SECONDARY (ES_STYLE_CAST(1635))
define ES_STYLE_TEXT_RADIO_GROUP_LABEL (ES_STYLE_CAST(1651))
define ES_STYLE_TEXT_TOOLBAR (ES_STYLE_CAST(1553))
define ES_STYLE_TEXTBOX_BORDERED_MULTILINE (ES_STYLE_CAST(1399))
define ES_STYLE_TEXTBOX_BORDERED_SINGLE (ES_STYLE_CAST(1401))

View File

@ -904,6 +904,6 @@ 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);
EsError EsDeviceControl(EsHandle handle, EsDeviceControlType type, void *dp, void *dq) {
return EsSyscall(ES_SYSCALL_DEVICE_CONTROL, handle, type, (uintptr_t) dp, (uintptr_t) dq);
}

View File

@ -540,6 +540,20 @@ EsFontFamily FontGetStandardFamily(EsFontFamily family) {
}
}
bool EsFontDatabaseLookupByName(const char *name, ptrdiff_t nameBytes, EsFontInformation *information) {
FontInitialise();
EsMemoryZero(information, sizeof(EsFontInformation));
for (uintptr_t i = 0; i < fontManagement.database.Length(); i++) {
if (0 == EsStringCompare(name, nameBytes, fontManagement.database[i].name, fontManagement.database[i].nameBytes)) {
EsMemoryCopy(information, &fontManagement.database[i], sizeof(EsFontInformation));
return true;
}
}
return false;
}
bool EsFontDatabaseLookupByID(EsFontFamily id, EsFontInformation *information) {
FontInitialise();
EsMemoryZero(information, sizeof(EsFontInformation));

View File

@ -8,14 +8,15 @@
// TODO Renaming directories does not work?
// TODO ESFS_CHECK_XXX are used to report out of memory errors, which shouldn't report KERNEL_PROBLEM_DAMAGED_FILESYSTEM.
#define ESFS_CHECK(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return false; }
#define ESFS_CHECK_ERROR(x, y) if ((x) != ES_SUCCESS) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return x; }
#define ESFS_CHECK_TO_ERROR(x, y, z) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return z; }
#define ESFS_CHECK_VA(x, y, ...) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n", __VA_ARGS__); return false; }
#define ESFS_CHECK_RETURN(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return; }
#define ESFS_CHECK_CORRUPT(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return ES_ERROR_CORRUPT_DATA; }
#define ESFS_CHECK_FATAL(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", "Mount - " y "\n"); return false; }
#define ESFS_CHECK_READ_ONLY(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "mount read only", "Mount - " y " Mounting as read only.\n"); volume->readOnly = true; }
#define ESFS_CHECK(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return false; }
#define ESFS_CHECK_ERROR(x, y) if ((x) != ES_SUCCESS) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return x; }
#define ESFS_CHECK_TO_ERROR(x, y, z) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return z; }
#define ESFS_CHECK_VA(x, y, ...) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n", __VA_ARGS__); return false; }
#define ESFS_CHECK_RETURN(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return; }
#define ESFS_CHECK_CORRUPT(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", y "\n"); return ES_ERROR_CORRUPT_DATA; }
#define ESFS_CHECK_FATAL(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "damaged file system", "Mount - " y "\n"); return false; }
#define ESFS_CHECK_READ_ONLY(x, y) if (!(x)) { KernelLog(LOG_ERROR, "EsFS", "mount read only", "Mount - " y " Mounting as read only.\n"); volume->readOnly = true; }
#define ESFS_CHECK_ERROR_READ_ONLY(x, y) if ((x) != ES_SUCCESS) { KernelLog(LOG_ERROR, "EsFS", "mount read only", "Mount - " y " Mounting as read only.\n"); volume->readOnly = true; }
struct Volume : KFileSystem {
Superblock superblock;
@ -38,9 +39,9 @@ struct FSNode {
static bool AccessBlock(Volume *volume, uint64_t index, uint64_t count, void *buffer, uint64_t flags, int driveAccess) {
// TODO Return EsError.
Superblock *superblock = &volume->superblock;
bool result = volume->Access(index * superblock->blockSize, count * superblock->blockSize, driveAccess, buffer, flags, nullptr);
ESFS_CHECK(result, "AccessBlock - Could not access blocks.");
return result;
EsError error = volume->Access(index * superblock->blockSize, count * superblock->blockSize, driveAccess, buffer, flags, nullptr);
ESFS_CHECK_ERROR(error, "AccessBlock - Could not access blocks.");
return error == ES_SUCCESS;
}
static bool ValidateIndexVertex(Superblock *superblock, IndexVertex *vertex) {
@ -67,7 +68,7 @@ static EsError FindDirectoryEntryReferenceFromIndex(Volume *volume, uint8_t *buf
uint64_t nameHash = CalculateCRC64(name, nameLength);
IndexVertex *vertex = (IndexVertex *) buffer;
if (!AccessBlock(volume, rootBlock, 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, rootBlock, 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
@ -84,7 +85,7 @@ static EsError FindDirectoryEntryReferenceFromIndex(Volume *volume, uint8_t *buf
if (i == vertex->count || keys[i].value > nameHash) {
if (keys[i].child) {
// The directory is in the child.
if (!AccessBlock(volume, keys[i].child, 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
if (!AccessBlock(volume, keys[i].child, 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
else goto nextVertex;
} else {
// We couldn't find the entry.
@ -173,7 +174,7 @@ static bool ReadWrite(FSNode *file, uint64_t offset, uint64_t count, uint8_t *bu
uint64_t accessBlockFlags = 0;
if (file->type == ES_NODE_DIRECTORY) {
accessBlockFlags |= BLOCK_ACCESS_CACHED;
accessBlockFlags |= FS_BLOCK_ACCESS_CACHED;
}
uint8_t *blockBuffer = !needBlockBuffer ? nullptr : (uint8_t *) EsHeapAllocate(superblock->blockSize, false, K_FIXED);
@ -344,7 +345,7 @@ static void Sync(KNode *_directory, KNode *node) {
EsDefer(EsHeapFree(blockBuffer, 0, K_FIXED));
ESFS_CHECK_RETURN(blockBuffer, "Sync - Could not allocate block buffer.");
if (!AccessBlock(volume, file->reference.block, 1, blockBuffer, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, file->reference.block, 1, blockBuffer, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Sync - Could not read reference block.\n");
return;
}
@ -355,7 +356,7 @@ static void Sync(KNode *_directory, KNode *node) {
EsMemoryCopy(blockBuffer + file->reference.offsetIntoBlock, &file->entry, sizeof(DirectoryEntry));
if (!AccessBlock(volume, file->reference.block, 1, blockBuffer, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
if (!AccessBlock(volume, file->reference.block, 1, blockBuffer, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Sync - Could not write reference block.\n");
return;
}
@ -528,7 +529,7 @@ static bool AllocateExtent(Volume *volume, uint64_t nearby, uint64_t increaseBlo
{
if (target->blockBitmap) {
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
return false;
}
@ -571,7 +572,7 @@ static bool AllocateExtent(Volume *volume, uint64_t nearby, uint64_t increaseBlo
bitmap[i / 8] |= 1 << (i % 8);
}
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
return false;
}
@ -634,7 +635,7 @@ static bool FreeExtent(Volume *volume, uint64_t extentStart, uint64_t extentCoun
ESFS_CHECK(bitmap, "FreeExtent - Could not allocate buffer for block bitmap.");
ESFS_CHECK(target->blockBitmap, "FreeExtent - Group descriptor does not have block bitmap.");
ESFS_CHECK(target->blocksUsed >= extentCount, "FreeExtent - Group descriptor indicates fewer blocks are used than are given in this extent.");
ESFS_CHECK(AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "FreeExtent - Could not read block bitmap.");
ESFS_CHECK(AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "FreeExtent - Could not read block bitmap.");
ESFS_CHECK(ValidateBlockBitmap(target, bitmap, superblock), "FreeExtent - Invalid block bitmap.");
// Clear the bits representing the freed blocks.
@ -648,7 +649,7 @@ static bool FreeExtent(Volume *volume, uint64_t extentStart, uint64_t extentCoun
// Write out the modified bitmap and update the group descriptor.
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
if (!AccessBlock(volume, target->blockBitmap, superblock->blocksPerGroupBlockBitmap, bitmap, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE)) {
return false;
}
@ -946,7 +947,7 @@ static bool IndexModifyKey(Volume *volume, uint64_t newKey, DirectoryEntryRefere
IndexVertex *vertex = (IndexVertex *) buffer;
uint64_t block;
if (!AccessBlock(volume, (block = rootBlock), 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, (block = rootBlock), 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
return false;
}
@ -963,7 +964,7 @@ static bool IndexModifyKey(Volume *volume, uint64_t newKey, DirectoryEntryRefere
if (i == vertex->count || keys[i].value > newKey) {
if (keys[i].child) {
// The directory is in the child.
if (!AccessBlock(volume, (block = keys[i].child), 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) return false;
if (!AccessBlock(volume, (block = keys[i].child), 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) return false;
else goto nextVertex;
} else {
// We couldn't find the entry.
@ -976,7 +977,7 @@ static bool IndexModifyKey(Volume *volume, uint64_t newKey, DirectoryEntryRefere
"IndexModifyKey - Invalid key entry.");
keys[i].data = reference;
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
return AccessBlock(volume, block, 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE);
return AccessBlock(volume, block, 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE);
}
}
@ -1021,7 +1022,7 @@ static bool IndexAddKey(Volume *volume, uint64_t newKey, DirectoryEntryReference
next:;
if (!skipFirst) {
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexAddKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexAddKey - Could not read index.");
if (!ValidateIndexVertex(superblock, vertex)) {
return false;
@ -1108,7 +1109,7 @@ static bool IndexAddKey(Volume *volume, uint64_t newKey, DirectoryEntryReference
parent->keys[0].child = blocks[1];
*rootBlock = blocks[0];
} else {
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexAddKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexAddKey - Could not read index.");
}
IndexKey *parentKeys = (IndexKey *) ((uint8_t *) parent + parent->offset);
@ -1155,8 +1156,8 @@ static bool IndexAddKey(Volume *volume, uint64_t newKey, DirectoryEntryReference
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock->blockSize);
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, siblingBlock, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
ESFS_CHECK(AccessBlock(volume, siblingBlock, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
// Check if the parent vertex is full.
@ -1167,7 +1168,7 @@ static bool IndexAddKey(Volume *volume, uint64_t newKey, DirectoryEntryReference
// Write the block.
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexAddKey - Could not update index.");
return true;
}
@ -1193,7 +1194,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
next:;
int i;
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (!ValidateIndexVertex(superblock, vertex)) return false;
for (i = 0; i <= vertex->count; i++) {
@ -1224,7 +1225,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
blocks[++depth] = ESFS_VERTEX_KEY(vertex, position + 1)->child;
while (true) {
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, search, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, search, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (!ValidateIndexVertex(superblock, search)) return false;
if (ESFS_VERTEX_KEY(search, 0)->child) {
@ -1237,7 +1238,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
ESFS_VERTEX_KEY(vertex, position)->data = ESFS_VERTEX_KEY(search, 0)->data;
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, blocks[startDepth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[startDepth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
EsMemoryCopy(vertex, search, superblock->blockSize);
position = 0;
@ -1256,7 +1257,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
if (vertex->count >= (vertex->maxCount - 1) / 2) {
// EsPrint("Vertex has enough keys, exiting...\n");
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
return true;
}
@ -1273,7 +1274,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
} else {
// EsPrint("Vertex is at root, exiting...\n");
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
}
return true;
@ -1283,7 +1284,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
uint8_t *buffer2 = blockBuffers + 1 * superblock->blockSize;
IndexVertex *parent = (IndexVertex *) buffer2;
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (!ValidateIndexVertex(superblock, parent)) return false;
int positionInParent = -1;
@ -1301,7 +1302,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
IndexVertex *sibling = (IndexVertex *) buffer3;
if (positionInParent) {
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (sibling->count > (sibling->maxCount - 1) / 2) {
// Steal left.
@ -1320,16 +1321,16 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock->blockSize);
parent->checksum = 0; parent->checksum = CalculateCRC32(parent, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
return true;
}
}
if (positionInParent != parent->count) {
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent + 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent + 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (sibling->count > (sibling->maxCount - 1) / 2) {
// Steal right.
@ -1348,9 +1349,9 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock->blockSize);
parent->checksum = 0; parent->checksum = CalculateCRC32(parent, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent + 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent + 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth - 1], 1, parent, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
return true;
}
@ -1363,10 +1364,10 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
EsMemoryCopy(sibling, vertex, superblock->blockSize);
positionInParent = 1;
blocks[depth] = ESFS_VERTEX_KEY(parent, positionInParent)->child;
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, blocks[depth], 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (!ValidateIndexVertex(superblock, vertex)) return false;
} else {
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "IndexRemoveKey - Could not read index.");
if (!ValidateIndexVertex(superblock, sibling)) return false;
}
@ -1389,7 +1390,7 @@ static bool IndexRemoveKey(Volume *volume, uint64_t removeKey, uint64_t *rootBlo
}
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock->blockSize);
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
ESFS_CHECK(AccessBlock(volume, ESFS_VERTEX_KEY(parent, positionInParent - 1)->child, 1, sibling, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "IndexRemoveKey - Could not write index.");
EsMemoryCopy(vertex, parent, superblock->blockSize);
depth--;
@ -1416,7 +1417,7 @@ static EsError RemoveDirectoryEntry(FSNode *file, uint8_t *blockBuffers /* super
// EsPrint("\tpositionOfLastEntry = %d\n\tThis node Reference = %d/%d\n", positionOfLastEntry, file->reference.block, file->reference.offsetIntoBlock);
ESFS_CHECK_TO_ERROR(AccessBlock(volume, file->reference.block, 1, blockBuffers, BLOCK_ACCESS_CACHED, K_ACCESS_READ), "Remove - Could not load the container block.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
ESFS_CHECK_TO_ERROR(AccessBlock(volume, file->reference.block, 1, blockBuffers, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ), "Remove - Could not load the container block.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
ESFS_CHECK_TO_ERROR(ReadWrite(directory, positionOfLastEntry & ~(superblock->blockSize - 1), superblock->blockSize,
blockBuffers + superblock->blockSize, false, false), "Remove - Could not load the last block.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
ESFS_CHECK_TO_ERROR(0 == EsMemoryCompare(blockBuffers + file->reference.offsetIntoBlock, &file->entry, sizeof(DirectoryEntry)), "Remove - Inconsistent file entry.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
@ -1424,7 +1425,7 @@ static EsError RemoveDirectoryEntry(FSNode *file, uint8_t *blockBuffers /* super
DirectoryEntry *movedEntry = (DirectoryEntry *) (blockBuffers + superblock->blockSize + (positionOfLastEntry & (superblock->blockSize - 1)));
DirectoryEntry *deletedEntry = (DirectoryEntry *) (blockBuffers + file->reference.offsetIntoBlock);
EsMemoryCopy(deletedEntry, movedEntry, sizeof(DirectoryEntry));
ESFS_CHECK_TO_ERROR(AccessBlock(volume, file->reference.block, 1, blockBuffers, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "Remove - Could not save the container block.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
ESFS_CHECK_TO_ERROR(AccessBlock(volume, file->reference.block, 1, blockBuffers, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE), "Remove - Could not save the container block.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
// Step 2: Update the node for the moved entry.
@ -1490,7 +1491,7 @@ static EsError Remove(KNode *_directory, KNode *node) {
if (attribute->indexRootBlock) {
IndexVertex *vertex = (IndexVertex *) blockBuffers;
ESFS_CHECK_TO_ERROR(AccessBlock(volume, attribute->indexRootBlock, 1, vertex, BLOCK_ACCESS_CACHED, K_ACCESS_READ),
ESFS_CHECK_TO_ERROR(AccessBlock(volume, attribute->indexRootBlock, 1, vertex, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ),
"Remove - Could not access index root.", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
ESFS_CHECK_TO_ERROR(!vertex->count, "Remove - Index was not empty (although it should be as the directory is empty).", ES_ERROR_CORRUPT_DATA);
KWriterLockTake(&volume->blockBitmapLock, K_LOCK_EXCLUSIVE);
@ -1719,7 +1720,7 @@ static EsError Load(KNode *_directory, KNode *_node, KNodeMetadata *, const void
if (!blockBuffer) return ES_ERROR_INSUFFICIENT_RESOURCES;
EsDefer(EsHeapFree(blockBuffer, 0, K_FIXED));
if (!AccessBlock(directory->volume, reference.block, 1, blockBuffer, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(directory->volume, reference.block, 1, blockBuffer, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Load - Could not load directory entry.\n");
return ES_ERROR_UNKNOWN;
}
@ -1781,7 +1782,7 @@ static EsError Scan(const char *name, size_t nameLength, KNode *_directory) {
// EsPrint("\t%d/%d\n", reference.block, reference.offsetIntoBlock);
if (!AccessBlock(volume, reference.block, 1, blockBuffer, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, reference.block, 1, blockBuffer, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Scan - Could not load directory entry.\n");
return ES_ERROR_UNKNOWN;
}
@ -1828,7 +1829,7 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
Superblock *superblock = &volume->superblock;
if (!volume->Access(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE, K_ACCESS_READ, (uint8_t *) superblock, ES_FLAGS_DEFAULT)) {
if (ES_SUCCESS != volume->Access(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE, K_ACCESS_READ, (uint8_t *) superblock, ES_FLAGS_DEFAULT)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Mount - Could not read superblock.\n");
return false;
}
@ -1869,7 +1870,7 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
superblock->mounted = true;
superblock->checksum = 0;
superblock->checksum = CalculateCRC32(superblock, sizeof(Superblock));
ESFS_CHECK_READ_ONLY(volume->Access(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE,
ESFS_CHECK_ERROR_READ_ONLY(volume->Access(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE,
K_ACCESS_WRITE, (uint8_t *) superblock, ES_FLAGS_DEFAULT), "Could not mark volume as mounted.");
}
@ -1879,7 +1880,7 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
volume->groupDescriptorTable = (GroupDescriptor *) EsHeapAllocate((superblock->groupCount * sizeof(GroupDescriptor) + superblock->blockSize - 1), false, K_FIXED);
if (!AccessBlock(volume, superblock->gdtFirstBlock, (superblock->groupCount * sizeof(GroupDescriptor) + superblock->blockSize - 1) / superblock->blockSize,
volume->groupDescriptorTable, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
volume->groupDescriptorTable, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
EsHeapFree(volume->groupDescriptorTable, 0, K_FIXED);
ESFS_CHECK_FATAL(false, "Could not read group descriptor table.");
}
@ -1900,7 +1901,7 @@ static bool Mount(Volume *volume, EsFileOffsetDifference *rootDirectoryChildren)
{
DirectoryEntryReference rootReference = superblock->root;
if (!AccessBlock(volume, rootReference.block, 1, blockBuffer, BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
if (!AccessBlock(volume, rootReference.block, 1, blockBuffer, FS_BLOCK_ACCESS_CACHED, K_ACCESS_READ)) {
KernelLog(LOG_ERROR, "EsFS", "drive access failure", "Mount - Could not load root directory.\n");
goto failure;
}
@ -1940,7 +1941,7 @@ static void Unmount(KFileSystem *fileSystem) {
if (!volume->readOnly) {
AccessBlock(volume, superblock->gdtFirstBlock, (superblock->groupCount * sizeof(GroupDescriptor) + superblock->blockSize - 1) / superblock->blockSize,
volume->groupDescriptorTable, BLOCK_ACCESS_CACHED, K_ACCESS_WRITE);
volume->groupDescriptorTable, FS_BLOCK_ACCESS_CACHED, K_ACCESS_WRITE);
superblock->mounted = false;
superblock->checksum = 0;

View File

@ -149,7 +149,7 @@ static bool Mount(Volume *volume) {
EsDefer(EsHeapFree(sectorBuffer, volume->block->information.sectorSize, K_FIXED));
{
if (!volume->Access(1024, volume->block->information.sectorSize, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
if (ES_SUCCESS != volume->Access(1024, volume->block->information.sectorSize, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not read boot sector.\n");
}
@ -187,7 +187,7 @@ static bool Mount(Volume *volume) {
MOUNT_FAILURE("Could not allocate the block group descriptor table.\n");
}
if (!volume->Access(firstBlockContainingBlockGroupDescriptorTable * volume->blockBytes,
if (ES_SUCCESS != volume->Access(firstBlockContainingBlockGroupDescriptorTable * volume->blockBytes,
blockGroupDescriptorTableLengthInBlocks * volume->blockBytes,
K_ACCESS_READ, volume->blockGroupDescriptorTable, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not read the block group descriptor table from the drive.\n");
@ -206,7 +206,7 @@ static bool Mount(Volume *volume) {
BlockGroupDescriptor *blockGroupDescriptor = volume->blockGroupDescriptorTable + blockGroup;
if (!volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
if (ES_SUCCESS != volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
+ sectorInInodeTable * volume->block->information.sectorSize,
volume->block->information.sectorSize,
K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
@ -253,7 +253,7 @@ static uint32_t GetDataBlock(Volume *volume, Inode *node, uint64_t blockIndex, u
if (blockIndex < blockPointersPerBlock) {
offset = node->indirectBlockPointers[0] * volume->blockBytes;
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[blockIndex];
CHECK_BLOCK_INDEX();
return offset;
@ -264,10 +264,10 @@ static uint32_t GetDataBlock(Volume *volume, Inode *node, uint64_t blockIndex, u
if (blockIndex < blockPointersPerBlock * blockPointersPerBlock) {
offset = node->indirectBlockPointers[1] * volume->blockBytes;
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[blockIndex / blockPointersPerBlock];
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[blockIndex % blockPointersPerBlock];
CHECK_BLOCK_INDEX();
return offset;
@ -278,13 +278,13 @@ static uint32_t GetDataBlock(Volume *volume, Inode *node, uint64_t blockIndex, u
if (blockIndex < blockPointersPerBlock * blockPointersPerBlock * blockPointersPerBlock) {
offset = node->indirectBlockPointers[2] * volume->blockBytes;
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[blockIndex / blockPointersPerBlock / blockPointersPerBlock];
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[(blockIndex / blockPointersPerBlock) % blockPointersPerBlock];
CHECK_BLOCK_INDEX();
if (!volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
if (ES_SUCCESS != volume->Access(offset, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) GET_DATA_BLOCK_ACCESS_FAILURE();
offset = blockPointers[blockIndex % blockPointersPerBlock];
CHECK_BLOCK_INDEX();
return offset;
@ -295,7 +295,7 @@ static uint32_t GetDataBlock(Volume *volume, Inode *node, uint64_t blockIndex, u
}
static EsError Enumerate(KNode *node) {
#define ENUMERATE_FAILURE(message) do { KernelLog(LOG_ERROR, "Ext2", "enumerate failure", "Enumerate - " message); return ES_ERROR_UNKNOWN; } while (0)
#define ENUMERATE_FAILURE(message, error) do { KernelLog(LOG_ERROR, "Ext2", "enumerate failure", "Enumerate - " message); return error; } while (0)
FSNode *directory = (FSNode *) node->driverNode;
Volume *volume = directory->volume;
@ -303,7 +303,7 @@ static EsError Enumerate(KNode *node) {
uint8_t *blockBuffer = (uint8_t *) EsHeapAllocate(volume->blockBytes, false, K_FIXED);
if (!blockBuffer) {
ENUMERATE_FAILURE("Could not allocate buffer.\n");
ENUMERATE_FAILURE("Could not allocate buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(blockBuffer, volume->blockBytes, K_FIXED));
@ -317,9 +317,8 @@ static EsError Enumerate(KNode *node) {
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
if (!volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) {
ENUMERATE_FAILURE("Could not read block.\n");
}
EsError error = volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) ENUMERATE_FAILURE("Could not read block.\n", error);
uintptr_t positionInBlock = 0;
@ -328,7 +327,7 @@ static EsError Enumerate(KNode *node) {
if (entry->entrySize > volume->blockBytes - positionInBlock
|| entry->nameLengthLow > volume->blockBytes - positionInBlock - sizeof(DirectoryEntry)) {
ENUMERATE_FAILURE("Invalid directory entry size.\n");
ENUMERATE_FAILURE("Invalid directory entry size.\n", ES_ERROR_CORRUPT_DATA);
}
KNodeMetadata metadata = {};
@ -360,7 +359,7 @@ static EsError Enumerate(KNode *node) {
}
static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
#define SCAN_FAILURE(message) do { KernelLog(LOG_ERROR, "Ext2", "scan failure", "Scan - " message); return ES_ERROR_UNKNOWN; } while (0)
#define SCAN_FAILURE(message, error) do { KernelLog(LOG_ERROR, "Ext2", "scan failure", "Scan - " message); return error; } while (0)
if (nameBytes == 2 && name[0] == '.' && name[1] == '.') return ES_ERROR_FILE_DOES_NOT_EXIST;
if (nameBytes == 1 && name[0] == '.') return ES_ERROR_FILE_DOES_NOT_EXIST;
@ -372,7 +371,7 @@ static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
uint8_t *blockBuffer = (uint8_t *) EsHeapAllocate(volume->blockBytes, false, K_FIXED);
if (!blockBuffer) {
SCAN_FAILURE("Could not allocate buffer.\n");
SCAN_FAILURE("Could not allocate buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(blockBuffer, volume->blockBytes, K_FIXED));
@ -384,12 +383,11 @@ static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
uint32_t block = GetDataBlock(volume, &directory->inode, i, blockBuffer);
if (!block) {
return ES_ERROR_UNKNOWN;
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
if (!volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) {
SCAN_FAILURE("Could not read block.\n");
}
EsError error = volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) SCAN_FAILURE("Could not read block.\n", error);
uintptr_t positionInBlock = 0;
@ -398,7 +396,7 @@ static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
if (entry->entrySize > volume->blockBytes - positionInBlock
|| entry->nameLengthLow > volume->blockBytes - positionInBlock - sizeof(DirectoryEntry)) {
SCAN_FAILURE("Invalid directory entry size.\n");
SCAN_FAILURE("Invalid directory entry size.\n", ES_ERROR_CORRUPT_DATA);
}
if (entry->nameLengthLow == nameBytes && 0 == EsMemoryCompare(name, blockBuffer + positionInBlock + sizeof(DirectoryEntry), nameBytes)) {
@ -415,7 +413,7 @@ static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
foundInode:;
if (inode >= volume->superBlock.inodeCount || inode == 0) {
SCAN_FAILURE("Invalid inode index.\n");
SCAN_FAILURE("Invalid inode index.\n", ES_ERROR_CORRUPT_DATA);
}
KNodeMetadata metadata = {};
@ -426,7 +424,7 @@ static EsError Scan(const char *name, size_t nameBytes, KNode *_directory) {
} else if (entry->type == DIRENT_TYPE_REGULAR) {
metadata.type = ES_NODE_FILE;
} else {
SCAN_FAILURE("Unsupported file type.\n");
SCAN_FAILURE("Unsupported file type.\n", ES_ERROR_UNSUPPORTED_FEATURE);
}
return FSDirectoryEntryFound(_directory, &metadata, &inode, name, nameBytes, false);
@ -453,12 +451,11 @@ static EsError Load(KNode *_directory, KNode *node, KNodeMetadata *metadata, con
BlockGroupDescriptor *blockGroupDescriptor = volume->blockGroupDescriptorTable + blockGroup;
if (!volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
+ sectorInInodeTable * volume->block->information.sectorSize,
volume->block->information.sectorSize,
K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) {
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
EsError error = volume->Access(blockGroupDescriptor->inodeTable * volume->blockBytes
+ sectorInInodeTable * volume->block->information.sectorSize,
volume->block->information.sectorSize,
K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) return error;
FSNode *data = (FSNode *) EsHeapAllocate(sizeof(FSNode), true, K_FIXED);
@ -528,7 +525,7 @@ struct ReadDispatchGroup : KWorkGroup {
};
static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset count) {
#define READ_FAILURE(message) do { KernelLog(LOG_ERROR, "Ext2", "read failure", "Read - " message); return ES_ERROR_UNKNOWN; } while (0)
#define READ_FAILURE(message, error) do { KernelLog(LOG_ERROR, "Ext2", "read failure", "Read - " message); return error; } while (0)
FSNode *file = (FSNode *) node->driverNode;
Volume *volume = file->volume;
@ -536,7 +533,7 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
uint8_t *blockBuffer = (uint8_t *) EsHeapAllocate(volume->blockBytes, false, K_FIXED);
if (!blockBuffer) {
READ_FAILURE("Could not allocate sector buffer.\n");
READ_FAILURE("Could not allocate sector buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(blockBuffer, volume->blockBytes, K_FIXED));
@ -567,9 +564,8 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
dispatchGroup.QueueBlock(volume, block, outputBuffer + outputPosition);
outputPosition += volume->blockBytes;
} else {
if (!volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT)) {
READ_FAILURE("Could not read blocks from drive.\n");
}
EsError error = volume->Access((uint64_t) block * volume->blockBytes, volume->blockBytes, K_ACCESS_READ, blockBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) READ_FAILURE("Could not read blocks from drive.\n", error);
EsMemoryCopy(outputBuffer + outputPosition, blockBuffer + readStart, readEnd - readStart);
outputPosition += readEnd - readStart;
@ -581,11 +577,10 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
bool success = dispatchGroup.Read();
if (!success) {
READ_FAILURE("Could not read blocks from drive.\n");
return false;
READ_FAILURE("Could not read blocks from drive.\n", ES_ERROR_DRIVE_CONTROLLER_REPORTED);
}
return true;
return count;
}
static void Close(KNode *node) {

View File

@ -152,10 +152,9 @@ static EsError Load(KNode *_directory, KNode *_node, KNodeMetadata *, const void
DirectoryEntry entry;
if (!directory->rootDirectory) {
if (!volume->Access((reference.cluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT)) {
return ES_ERROR_UNKNOWN;
}
EsError error = volume->Access((reference.cluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) return error;
entry = *(DirectoryEntry *) (clusterBuffer + reference.offset);
} else {
@ -177,7 +176,7 @@ static EsError Load(KNode *_directory, KNode *_node, KNodeMetadata *, const void
}
static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset count) {
#define READ_FAILURE(message) do { KernelLog(LOG_ERROR, "FAT", "read failure", "Read - " message); return ES_ERROR_UNKNOWN; } while (0)
#define READ_FAILURE(message, error) do { KernelLog(LOG_ERROR, "FAT", "read failure", "Read - " message); return error; } while (0)
FSNode *file = (FSNode *) node->driverNode;
Volume *volume = file->volume;
@ -185,7 +184,7 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
uint8_t *clusterBuffer = (uint8_t *) EsHeapAllocate(superBlock->sectorsPerCluster * SECTOR_SIZE, false, K_FIXED);
EsDefer(EsHeapFree(clusterBuffer, 0, K_FIXED));
if (!clusterBuffer) READ_FAILURE("Could not allocate cluster buffer.\n");
if (!clusterBuffer) READ_FAILURE("Could not allocate cluster buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
uint8_t *outputBuffer = (uint8_t *) _buffer;
uint64_t firstCluster = offset / (SECTOR_SIZE * superBlock->sectorsPerCluster);
@ -197,11 +196,10 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
uint32_t bytesFromThisCluster = superBlock->sectorsPerCluster * SECTOR_SIZE - offset;
if (bytesFromThisCluster > count) bytesFromThisCluster = count;
if (!volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ,
(uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT)) {
READ_FAILURE("Could not read cluster.\n");
}
EsError error = volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ,
(uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) READ_FAILURE("Could not read cluster.\n", error);
EsMemoryCopy(outputBuffer, clusterBuffer + offset, bytesFromThisCluster);
count -= bytesFromThisCluster, outputBuffer += bytesFromThisCluster, offset = 0;
@ -212,8 +210,7 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
}
static EsError Scan(const char *_name, size_t nameLength, KNode *node) {
#define SCAN_FAILURE(message) do { KernelLog(LOG_ERROR, "FAT", "scan failure", "Scan - " message); return ES_ERROR_UNKNOWN; } while (0)
#define SCAN_FAILURE_2(message) do { KernelLog(LOG_ERROR, "FAT", "scan failure", "Scan - " message); goto failure; } while (0)
#define SCAN_FAILURE(message, error) do { KernelLog(LOG_ERROR, "FAT", "scan failure", "Scan - " message); return error; } while (0)
uint8_t name[] = " ";
@ -235,17 +232,16 @@ static EsError Scan(const char *_name, size_t nameLength, KNode *node) {
uint8_t *clusterBuffer = (uint8_t *) EsHeapAllocate(superBlock->sectorsPerCluster * SECTOR_SIZE, false, K_FIXED);
EsDefer(EsHeapFree(clusterBuffer, 0, K_FIXED));
if (!clusterBuffer) SCAN_FAILURE("Could not allocate cluster buffer.\n");
if (!clusterBuffer) SCAN_FAILURE("Could not allocate cluster buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
uint32_t currentCluster = directory->entry.firstClusterLow + (directory->entry.firstClusterHigh << 16);
uintptr_t directoryPosition = 0;
while (currentCluster < volume->terminateCluster) {
if (!directory->rootDirectory) {
if (!volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT)) {
SCAN_FAILURE("Could not read cluster.\n");
}
EsError error = volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) SCAN_FAILURE("Could not read cluster.\n", error);
}
for (uintptr_t i = 0; i < superBlock->sectorsPerCluster * SECTOR_SIZE / sizeof(DirectoryEntry); i++, directoryPosition++) {
@ -294,7 +290,7 @@ static EsError Scan(const char *_name, size_t nameLength, KNode *node) {
}
static EsError Enumerate(KNode *node) {
#define ENUMERATE_FAILURE(message) do { KernelLog(LOG_ERROR, "FAT", "enumerate failure", "Enumerate - " message); return ES_ERROR_UNKNOWN; } while (0)
#define ENUMERATE_FAILURE(message, error) do { KernelLog(LOG_ERROR, "FAT", "enumerate failure", "Enumerate - " message); return error; } while (0)
FSNode *directory = (FSNode *) node->driverNode;
Volume *volume = directory->volume;
@ -302,17 +298,16 @@ static EsError Enumerate(KNode *node) {
uint8_t *clusterBuffer = (uint8_t *) EsHeapAllocate(superBlock->sectorsPerCluster * SECTOR_SIZE, false, K_FIXED);
EsDefer(EsHeapFree(clusterBuffer, 0, K_FIXED));
if (!clusterBuffer) ENUMERATE_FAILURE("Could not allocate cluster buffer.\n");
if (!clusterBuffer) ENUMERATE_FAILURE("Could not allocate cluster buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
uint32_t currentCluster = directory->entry.firstClusterLow + (directory->entry.firstClusterHigh << 16);
uint64_t directoryPosition = 0;
while (currentCluster < volume->terminateCluster) {
if (!directory->rootDirectory) {
if (!volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT)) {
ENUMERATE_FAILURE("Could not read cluster.\n");
}
EsError error = volume->Access((currentCluster * superBlock->sectorsPerCluster + volume->sectorOffset) * SECTOR_SIZE,
superBlock->sectorsPerCluster * SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) clusterBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) ENUMERATE_FAILURE("Could not read cluster.\n", error);
}
for (uintptr_t i = 0; i < superBlock->sectorsPerCluster * SECTOR_SIZE / sizeof(DirectoryEntry); i++, directoryPosition++) {
@ -370,8 +365,10 @@ static bool Mount(Volume *volume) {
#define MOUNT_FAILURE(message) do { KernelLog(LOG_ERROR, "FAT", "mount failure", "Mount - " message); goto failure; } while (0)
{
EsError error;
SuperBlockCommon *superBlock = &volume->superBlock;
if (!volume->Access(0, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) superBlock, ES_FLAGS_DEFAULT)) MOUNT_FAILURE("Could not read superBlock.\n");
error = volume->Access(0, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) superBlock, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) MOUNT_FAILURE("Could not read super block.\n");
uint32_t sectorCount = superBlock->totalSectors ?: superBlock->largeSectorCount;
uint32_t clusterCount = sectorCount / superBlock->sectorsPerCluster;
@ -400,8 +397,8 @@ static bool Mount(Volume *volume) {
volume->fat = (uint8_t *) EsHeapAllocate(sectorsPerFAT * SECTOR_SIZE, true, K_FIXED);
if (!volume->fat) MOUNT_FAILURE("Could not allocate FAT.\n");
if (!volume->Access(superBlock->reservedSectors * SECTOR_SIZE,
sectorsPerFAT * SECTOR_SIZE, K_ACCESS_READ, volume->fat, ES_FLAGS_DEFAULT)) MOUNT_FAILURE("Could not read FAT.\n");
error = volume->Access(superBlock->reservedSectors * SECTOR_SIZE, sectorsPerFAT * SECTOR_SIZE, K_ACCESS_READ, volume->fat, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) MOUNT_FAILURE("Could not read FAT.\n");
volume->spaceUsed = CountUsedClusters(volume) * superBlock->sectorsPerCluster * superBlock->bytesPerSector;
volume->spaceTotal = volume->block->information.sectorSize * volume->block->information.sectorCount;
@ -426,10 +423,9 @@ static bool Mount(Volume *volume) {
root->rootDirectory = (DirectoryEntry *) EsHeapAllocate(rootDirectorySectors * SECTOR_SIZE, true, K_FIXED);
volume->rootDirectoryEntries = root->rootDirectory;
if (!volume->Access(rootDirectoryOffset * SECTOR_SIZE, rootDirectorySectors * SECTOR_SIZE,
K_ACCESS_READ, (uint8_t *) root->rootDirectory, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not read root directory.\n");
}
error = volume->Access(rootDirectoryOffset * SECTOR_SIZE, rootDirectorySectors * SECTOR_SIZE,
K_ACCESS_READ, (uint8_t *) root->rootDirectory, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) MOUNT_FAILURE("Could not read root directory.\n");
for (uintptr_t i = 0; i < superBlock->rootDirectoryEntries; i++) {
if (root->rootDirectory[i].name[0] == 0xE5 || root->rootDirectory[i].attributes == 0x0F || (root->rootDirectory[i].attributes & 0x08)) continue;

View File

@ -112,7 +112,7 @@ static bool Mount(Volume *volume) {
uintptr_t descriptorIndex = 0;
while (true) {
if (!volume->Access(32768 + SECTOR_SIZE * descriptorIndex, SECTOR_SIZE, K_ACCESS_READ, &volume->primaryDescriptor, ES_FLAGS_DEFAULT)) {
if (ES_SUCCESS != volume->Access(32768 + SECTOR_SIZE * descriptorIndex, SECTOR_SIZE, K_ACCESS_READ, &volume->primaryDescriptor, ES_FLAGS_DEFAULT)) {
MOUNT_FAILURE("Could not access descriptor list.\n");
}
@ -188,7 +188,7 @@ static bool Mount(Volume *volume) {
EsDefer(EsHeapFree(firstSector, SECTOR_SIZE, K_FIXED));
if (!volume->Access(record.extentStart.x * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, firstSector, ES_FLAGS_DEFAULT)) {
if (ES_SUCCESS != volume->Access(record.extentStart.x * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, firstSector, ES_FLAGS_DEFAULT)) {
goto notBoot;
}
@ -214,7 +214,7 @@ static bool Mount(Volume *volume) {
}
static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset count) {
#define READ_FAILURE(message) do { KernelLog(LOG_ERROR, "ISO9660", "read failure", "Read - " message); return ES_ERROR_UNKNOWN; } while (0)
#define READ_FAILURE(message, error) do { KernelLog(LOG_ERROR, "ISO9660", "read failure", "Read - " message); return error; } while (0)
FSNode *file = (FSNode *) node->driverNode;
Volume *volume = file->volume;
@ -222,7 +222,7 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(SECTOR_SIZE, false, K_FIXED);
if (!sectorBuffer) {
READ_FAILURE("Could not allocate sector buffer.\n");
READ_FAILURE("Could not allocate sector buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(sectorBuffer, SECTOR_SIZE, K_FIXED));
@ -235,9 +235,8 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
while (count) {
if (offset || count < SECTOR_SIZE) {
if (!volume->Access(lba * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT)) {
READ_FAILURE("Could not read file sector.\n");
}
EsError error = volume->Access(lba * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, sectorBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) READ_FAILURE("Could not read file sector.\n", error);
uint64_t bytesToRead = (count > SECTOR_SIZE - offset) ? (SECTOR_SIZE - offset) : count;
EsMemoryCopy(outputBuffer, sectorBuffer + offset, bytesToRead);
@ -245,11 +244,8 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
lba++, count -= bytesToRead, offset = 0, outputBuffer += bytesToRead;
} else {
uint64_t sectorsToRead = count / SECTOR_SIZE;
if (!volume->Access(lba * SECTOR_SIZE, sectorsToRead * SECTOR_SIZE, K_ACCESS_READ, outputBuffer, ES_FLAGS_DEFAULT)) {
READ_FAILURE("Could not read file sectors.\n");
}
EsError error = volume->Access(lba * SECTOR_SIZE, sectorsToRead * SECTOR_SIZE, K_ACCESS_READ, outputBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) READ_FAILURE("Could not read file sectors.\n", error);
lba += sectorsToRead, count -= SECTOR_SIZE * sectorsToRead, outputBuffer += SECTOR_SIZE * sectorsToRead;
}
}
@ -258,7 +254,7 @@ static size_t Read(KNode *node, void *_buffer, EsFileOffset offset, EsFileOffset
}
static EsError Enumerate(KNode *node) {
#define ENUMERATE_FAILURE(message) do { KernelLog(LOG_ERROR, "ISO9660", "enumerate failure", "Enumerate - " message); return false; } while (0)
#define ENUMERATE_FAILURE(message, error) do { KernelLog(LOG_ERROR, "ISO9660", "enumerate failure", "Enumerate - " message); return error; } while (0)
FSNode *directory = (FSNode *) node->driverNode;
Volume *volume = directory->volume;
@ -268,7 +264,7 @@ static EsError Enumerate(KNode *node) {
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(SECTOR_SIZE, false, K_FIXED);
if (!sectorBuffer) {
ENUMERATE_FAILURE("Could not allocate sector buffer.\n");
ENUMERATE_FAILURE("Could not allocate sector buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(sectorBuffer, SECTOR_SIZE, K_FIXED));
@ -277,10 +273,10 @@ static EsError Enumerate(KNode *node) {
uint32_t remainingBytes = directory->record.extentSize.x;
while (remainingBytes) {
bool accessResult = volume->Access(currentSector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT);
EsError accessResult = volume->Access(currentSector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT);
if (!accessResult) {
ENUMERATE_FAILURE("Could not read sector.\n");
if (accessResult != ES_SUCCESS) {
ENUMERATE_FAILURE("Could not read sector.\n", accessResult);
}
uintptr_t positionInSector = 0;
@ -293,7 +289,7 @@ static EsError Enumerate(KNode *node) {
}
if (positionInSector + record->length > SECTOR_SIZE || record->length < sizeof(DirectoryRecord)) {
ENUMERATE_FAILURE("Invalid directory record.\n");
ENUMERATE_FAILURE("Invalid directory record.\n", ES_ERROR_CORRUPT_DATA);
}
if (record->fileNameBytes <= 2) {
@ -348,7 +344,7 @@ static EsError Enumerate(KNode *node) {
}
static EsError ScanInternal(const char *name, size_t nameBytes, KNode *_directory, DirectoryRecord *_record) {
#define SCAN_FAILURE(message) do { KernelLog(LOG_ERROR, "ISO9660", "scan failure", "Scan - " message); return ES_ERROR_UNKNOWN; } while (0)
#define SCAN_FAILURE(message, error) do { KernelLog(LOG_ERROR, "ISO9660", "scan failure", "Scan - " message); return error; } while (0)
// Check for invalid characters.
@ -370,7 +366,7 @@ static EsError ScanInternal(const char *name, size_t nameBytes, KNode *_director
uint8_t *sectorBuffer = (uint8_t *) EsHeapAllocate(SECTOR_SIZE, false, K_FIXED);
if (!sectorBuffer) {
SCAN_FAILURE("Could not allocate sector buffer.\n");
SCAN_FAILURE("Could not allocate sector buffer.\n", ES_ERROR_INSUFFICIENT_RESOURCES);
}
EsDefer(EsHeapFree(sectorBuffer, SECTOR_SIZE, K_FIXED));
@ -379,10 +375,10 @@ static EsError ScanInternal(const char *name, size_t nameBytes, KNode *_director
uint32_t remainingBytes = directory->record.extentSize.x;
while (remainingBytes) {
bool accessResult = volume->Access(currentSector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT);
EsError accessResult = volume->Access(currentSector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT);
if (!accessResult) {
SCAN_FAILURE("Could not read sector.\n");
if (accessResult != ES_SUCCESS) {
SCAN_FAILURE("Could not read sector.\n", accessResult);
}
uintptr_t positionInSector = 0;
@ -395,7 +391,7 @@ static EsError ScanInternal(const char *name, size_t nameBytes, KNode *_director
}
if (positionInSector + record->length > SECTOR_SIZE || record->length < sizeof(DirectoryRecord)) {
SCAN_FAILURE("Invalid directory record.\n");
SCAN_FAILURE("Invalid directory record.\n", ES_ERROR_CORRUPT_DATA);
}
if (record->fileNameBytes <= 2) {
@ -464,9 +460,8 @@ static EsError Load(KNode *_directory, KNode *_node, KNodeMetadata *, const void
EsDefer(EsHeapFree(sectorBuffer, SECTOR_SIZE, K_FIXED));
if (!volume->Access(reference.sector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT)) {
return ES_ERROR_DRIVE_CONTROLLER_REPORTED;
}
EsError error = volume->Access(reference.sector * SECTOR_SIZE, SECTOR_SIZE, K_ACCESS_READ, (uint8_t *) sectorBuffer, ES_FLAGS_DEFAULT);
if (error != ES_SUCCESS) return error;
FSNode *data = (FSNode *) EsHeapAllocate(sizeof(FSNode), true, K_FIXED);

View File

@ -52,6 +52,12 @@ struct FSFile : KNode {
KWriterLock resizeLock; // Take exclusive for resizing or flushing.
};
struct KDMABuffer {
uintptr_t virtualAddress;
size_t totalByteCount;
uintptr_t offsetBytes;
};
EsError FSNodeOpenHandle(KNode *node, uint32_t flags, uint8_t mode);
void FSNodeCloseHandle(KNode *node, uint32_t flags);
EsError FSNodeDelete(KNode *node);
@ -61,6 +67,7 @@ ptrdiff_t FSDirectoryEnumerateChildren(KNode *node, K_USER_BUFFER EsDirectoryChi
EsError FSFileControl(KNode *node, uint32_t flags);
bool FSTrimCachedNode(MMObjectCache *);
bool FSTrimCachedDirectoryEntry(MMObjectCache *);
EsError FSBlockDeviceAccess(KBlockDeviceAccessRequest request);
struct {
KWriterLock fileSystemsLock;
@ -1489,12 +1496,6 @@ bool FSTrimCachedNode(MMObjectCache *cache) {
// DMA transfer buffers.
//////////////////////////////////////////
struct KDMABuffer {
uintptr_t virtualAddress;
size_t totalByteCount;
uintptr_t offsetBytes;
};
uintptr_t KDMABufferGetVirtualAddress(KDMABuffer *buffer) {
return buffer->virtualAddress;
}
@ -1539,29 +1540,33 @@ KDMASegment KDMABufferNextSegment(KDMABuffer *buffer, bool peek) {
// Block devices.
//////////////////////////////////////////
bool FSBlockDeviceAccess(KBlockDeviceAccessRequest request) {
EsError FSBlockDeviceAccess(KBlockDeviceAccessRequest request) {
KBlockDevice *device = request.device;
if (!request.count) {
return true;
return ES_SUCCESS;
}
if (device->information.readOnly && request.operation == K_ACCESS_WRITE) {
if (request.flags & FS_BLOCK_ACCESS_SOFT_ERRORS) return ES_ERROR_BLOCK_ACCESS_INVALID;
KernelPanic("FSBlockDeviceAccess - Drive %x is read-only.\n", device);
}
if (request.offset / device->information.sectorSize > device->information.sectorCount
|| (request.offset + request.count) / device->information.sectorSize > device->information.sectorCount) {
if (request.flags & FS_BLOCK_ACCESS_SOFT_ERRORS) return ES_ERROR_BLOCK_ACCESS_INVALID;
KernelPanic("FSBlockDeviceAccess - Access out of bounds on drive %x.\n", device);
}
if ((request.offset % device->information.sectorSize) || (request.count % device->information.sectorSize)) {
if (request.flags & FS_BLOCK_ACCESS_SOFT_ERRORS) return ES_ERROR_BLOCK_ACCESS_INVALID;
KernelPanic("FSBlockDeviceAccess - Misaligned access.\n");
}
KDMABuffer buffer = *request.buffer;
if (buffer.virtualAddress & 3) {
if (request.flags & FS_BLOCK_ACCESS_SOFT_ERRORS) return ES_ERROR_BLOCK_ACCESS_INVALID;
KernelPanic("FSBlockDeviceAccess - Buffer must be DWORD aligned.\n");
}
@ -1593,20 +1598,20 @@ bool FSBlockDeviceAccess(KBlockDeviceAccessRequest request) {
}
if (request.dispatchGroup == &fakeDispatchGroup) {
return fakeDispatchGroup.Wait();
return fakeDispatchGroup.Wait() ? ES_SUCCESS : ES_ERROR_DRIVE_CONTROLLER_REPORTED;
} else {
return true;
return ES_SUCCESS;
}
}
EsError FSReadIntoBlockCache(CCSpace *cache, void *buffer, EsFileOffset offset, EsFileOffset count) {
KFileSystem *fileSystem = EsContainerOf(KFileSystem, cacheSpace, cache);
return fileSystem->Access(offset, count, K_ACCESS_READ, buffer, ES_FLAGS_DEFAULT, nullptr) ? ES_SUCCESS : ES_ERROR_DRIVE_CONTROLLER_REPORTED;
return fileSystem->Access(offset, count, K_ACCESS_READ, buffer, ES_FLAGS_DEFAULT, nullptr);
}
EsError FSWriteFromBlockCache(CCSpace *cache, const void *buffer, EsFileOffset offset, EsFileOffset count) {
KFileSystem *fileSystem = EsContainerOf(KFileSystem, cacheSpace, cache);
return fileSystem->Access(offset, count, K_ACCESS_WRITE, (void *) buffer, ES_FLAGS_DEFAULT, nullptr) ? ES_SUCCESS : ES_ERROR_DRIVE_CONTROLLER_REPORTED;
return fileSystem->Access(offset, count, K_ACCESS_WRITE, (void *) buffer, ES_FLAGS_DEFAULT, nullptr);
}
const CCSpaceCallbacks fsBlockCacheCallbacks = {
@ -1614,19 +1619,19 @@ const CCSpaceCallbacks fsBlockCacheCallbacks = {
.writeFrom = FSWriteFromBlockCache,
};
bool KFileSystem::Access(EsFileOffset offset, size_t count, int operation, void *buffer, uint32_t flags, KWorkGroup *dispatchGroup) {
EsError KFileSystem::Access(EsFileOffset offset, size_t count, int operation, void *buffer, uint32_t flags, KWorkGroup *dispatchGroup) {
if (this->flags & K_DEVICE_REMOVED) {
if (dispatchGroup) {
dispatchGroup->Start();
dispatchGroup->End(false);
}
return false;
return ES_ERROR_DEVICE_REMOVED;
}
bool blockDeviceCachedEnabled = true;
if (blockDeviceCachedEnabled && (flags & BLOCK_ACCESS_CACHED)) {
if (blockDeviceCachedEnabled && (flags & FS_BLOCK_ACCESS_CACHED)) {
if (dispatchGroup) {
dispatchGroup->Start();
}
@ -1643,7 +1648,7 @@ bool KFileSystem::Access(EsFileOffset offset, size_t count, int operation, void
dispatchGroup->End(result == ES_SUCCESS);
}
return result == ES_SUCCESS;
return result;
} else {
KDMABuffer dmaBuffer = { (uintptr_t) buffer, count };
KBlockDeviceAccessRequest request = {};
@ -1726,48 +1731,21 @@ bool FSSignatureCheck(KInstalledDriver *driver, KDevice *device) {
}
bool FSCheckMBR(KBlockDevice *device) {
if (device->signatureBlock[510] != 0x55 || device->signatureBlock[511] != 0xAA) {
MBRPartition partitions[4];
if (MBRGetPartitions(device->signatureBlock, device->information.sectorCount, partitions)) {
for (uintptr_t i = 0; i < 4; i++) {
if (partitions[i].present) {
KernelLog(LOG_INFO, "FS", "MBR partition", "Found MBR partition %d with offset %d and count %d.\n",
i, partitions[i].offset, partitions[i].count);
FSPartitionDeviceCreate(device, partitions[i].offset, partitions[i].count, FS_PARTITION_DEVICE_NO_MBR, EsLiteral("MBR partition"));
}
}
return true;
} else {
return false;
}
KernelLog(LOG_INFO, "FS", "probing MBR", "First sector on device looks like an MBR...\n");
uint32_t offsets[4], counts[4];
bool present[4] = {};
for (uintptr_t i = 0; i < 4; i++) {
if (!device->signatureBlock[4 + 0x1BE + i * 0x10]) {
continue;
}
offsets[i] =
((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->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->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;
}
}
for (uintptr_t i = 0; i < 4; i++) {
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, EsLiteral("MBR partition"));
}
}
return true;
}
bool FSFileSystemInitialise(KFileSystem *fileSystem) {
@ -1821,7 +1799,7 @@ void FSDetectFileSystem(KBlockDevice *device) {
request.operation = K_ACCESS_READ;
request.buffer = &dmaBuffer;
if (!FSBlockDeviceAccess(request)) {
if (ES_SUCCESS != FSBlockDeviceAccess(request)) {
// 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 {

View File

@ -126,6 +126,7 @@ KSpinlock ipiLock;
#include <shared/arena.cpp>
#else
#include <shared/array.cpp>
#include <shared/partitions.cpp>
#endif
#include "objects.cpp"

View File

@ -843,11 +843,11 @@ struct KFileSystem : KDevice {
// Only use this for file system metadata that isn't cached in a Node.
// This must be used consistently, i.e. if you ever read a region cached, then you must always write that region cached, and vice versa.
#define BLOCK_ACCESS_CACHED (1)
#define FS_BLOCK_ACCESS_CACHED (1)
#define FS_BLOCK_ACCESS_SOFT_ERRORS (2)
// Access the block device. Returns true on success.
// Offset and count must be sector aligned. Buffer must be DWORD aligned.
// TODO Make this return EsError.
bool Access(EsFileOffset offset, size_t count, int operation, void *buffer, uint32_t flags, KWorkGroup *dispatchGroup = nullptr);
EsError Access(EsFileOffset offset, size_t count, int operation, void *buffer, uint32_t flags, KWorkGroup *dispatchGroup = nullptr);
// Fill these fields in before registering the file system:

View File

@ -380,7 +380,7 @@ namespace POSIX {
case SYS_read: {
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, false);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, true);
return Read(file, (void *) syscall.arguments[1], syscall.arguments[2], _region3->flags & MM_REGION_FILE);
} break;
@ -398,7 +398,7 @@ namespace POSIX {
for (uintptr_t i = 0; i < (uintptr_t) syscall.arguments[2]; i++) {
if (!vectors[i].iov_len) continue;
SYSCALL_BUFFER_POSIX((uintptr_t) vectors[i].iov_base, vectors[i].iov_len, 3, false);
SYSCALL_BUFFER_POSIX((uintptr_t) vectors[i].iov_base, vectors[i].iov_len, 3, true);
intptr_t result = Read(file, vectors[i].iov_base, vectors[i].iov_len, _region3->flags & MM_REGION_FILE);
if (result < 0) return result;
bytesRead += result;
@ -409,7 +409,7 @@ namespace POSIX {
case SYS_write: {
SYSCALL_HANDLE_POSIX(syscall.arguments[0], file);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, true);
SYSCALL_BUFFER_POSIX(syscall.arguments[1], syscall.arguments[2], 3, false);
if (file->type == POSIX_FILE_NORMAL && !(file->openFlags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE))) {
return -EACCES;
@ -437,7 +437,7 @@ namespace POSIX {
for (uintptr_t i = 0; i < (uintptr_t) syscall.arguments[2]; i++) {
if (!vectors[i].iov_len) continue;
// EsPrint("writev %d: %x/%d\n", i, vectors[i].iov_base, vectors[i].iov_len);
SYSCALL_BUFFER_POSIX((uintptr_t) vectors[i].iov_base, vectors[i].iov_len, 3, true);
SYSCALL_BUFFER_POSIX((uintptr_t) vectors[i].iov_base, vectors[i].iov_len, 3, false);
intptr_t result = Write(file, vectors[i].iov_base, vectors[i].iov_len, _region3->flags & MM_REGION_FILE);
if (result < 0) return result;
bytesWritten += result;

View File

@ -851,7 +851,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_FILE_READ_SYNC) {
if (file->directoryEntry->type != ES_NODE_FILE) SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_NODE_TYPE, true);
SYSCALL_BUFFER(argument3, argument2, 1, false);
SYSCALL_BUFFER(argument3, argument2, 1, true /* we're writing into this buffer */);
size_t result = FSFileReadSync(file, (void *) argument3, argument1, argument2,
(_region1->flags & MM_REGION_FILE) ? FS_FILE_ACCESS_USER_BUFFER_MAPPED : 0);
@ -866,7 +866,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_FILE_WRITE_SYNC) {
if (file->directoryEntry->type != ES_NODE_FILE) SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_NODE_TYPE, true);
SYSCALL_BUFFER(argument3, argument2, 1, true /* write */);
SYSCALL_BUFFER(argument3, argument2, 1, false);
if (handle.flags & (ES_FILE_WRITE_SHARED | ES_FILE_WRITE)) {
size_t result = FSFileWriteSync(file, (void *) argument3, argument1, argument2,
@ -1823,12 +1823,28 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_CONNECTION_NOTIFY) {
SYSCALL_IMPLEMENT(ES_SYSCALL_DEVICE_CONTROL) {
SYSCALL_HANDLE(argument0, KERNEL_OBJECT_DEVICE, device, KDevice);
EsDeviceControlType type = (EsDeviceControlType) argument1;
uintptr_t dp = argument2, dq = argument3;
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));
if (type == ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION) {
SYSCALL_WRITE(dp, &block->information, sizeof(EsBlockDeviceInformation));
} else if (type == ES_DEVICE_CONTROL_BLOCK_READ || type == ES_DEVICE_CONTROL_BLOCK_WRITE) {
bool write = type == ES_DEVICE_CONTROL_BLOCK_WRITE;
KDMABuffer dmaBuffer = { dp, block->information.sectorSize };
EsFileOffset parameters[2];
SYSCALL_READ(parameters, dq, sizeof(EsFileOffset) * 2);
SYSCALL_BUFFER(dp, parameters[1], 1, !write /* whether the buffer will be written to */);
KBlockDeviceAccessRequest request = {};
request.device = block;
request.offset = parameters[0];
request.count = parameters[1];
request.operation = write ? K_ACCESS_WRITE : K_ACCESS_READ;
request.buffer = &dmaBuffer;
request.flags = FS_BLOCK_ACCESS_SOFT_ERRORS;
SYSCALL_RETURN(FSBlockDeviceAccess(request), false);
} else {
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
}

Binary file not shown.

Binary file not shown.

View File

@ -519,7 +519,10 @@ void AccessNode(DirectoryEntry *node, void *buffer, uint64_t offsetIntoFile, uin
}
uint8_t blockBuffer[superblock.blockSize];
ReadBlock(block, 1, blockBuffer);
if (read || count != superblock.blockSize) {
ReadBlock(block, 1, blockBuffer);
}
if (read) {
memcpy(buffer, blockBuffer + offset, count);

55
shared/partitions.cpp Normal file
View File

@ -0,0 +1,55 @@
typedef struct MBRPartition {
uint32_t offset, count;
bool present;
} MBRPartition;
bool MBRGetPartitions(uint8_t *firstBlock, EsFileOffset sectorCount, MBRPartition *partitions) {
if (firstBlock[510] != 0x55 || firstBlock[511] != 0xAA) {
return false;
}
#ifdef KERNEL
KernelLog(LOG_INFO, "FS", "probing MBR", "First sector on device looks like an MBR...\n");
#endif
for (uintptr_t i = 0; i < 4; i++) {
if (!firstBlock[4 + 0x1BE + i * 0x10]) {
partitions[i].present = false;
continue;
}
partitions[i].offset =
((uint32_t) firstBlock[0x1BE + i * 0x10 + 8 ] << 0)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 9 ] << 8)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 10] << 16)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 11] << 24);
partitions[i].count =
((uint32_t) firstBlock[0x1BE + i * 0x10 + 12] << 0)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 13] << 8)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 14] << 16)
+ ((uint32_t) firstBlock[0x1BE + i * 0x10 + 15] << 24);
partitions[i].present = true;
if (partitions[i].offset > sectorCount || partitions[i].count > sectorCount - partitions[i].offset || partitions[i].count < 32) {
#ifdef KERNEL
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, partitions[i].offset, partitions[i].count);
#endif
return false;
}
}
return true;
}
void MBRFixPartition(uint32_t *partitions) {
uint32_t headsPerCylinder = 256, sectorsPerTrack = 63;
uint32_t partitionOffsetCylinder = (partitions[2] / sectorsPerTrack) / headsPerCylinder;
uint32_t partitionOffsetHead = (partitions[2] / sectorsPerTrack) % headsPerCylinder;
uint32_t partitionOffsetSector = (partitions[2] % sectorsPerTrack) + 1;
uint32_t partitionSizeCylinder = (partitions[3] / sectorsPerTrack) / headsPerCylinder;
uint32_t partitionSizeHead = (partitions[3] / sectorsPerTrack) % headsPerCylinder;
uint32_t partitionSizeSector = (partitions[3] % sectorsPerTrack) + 1;
partitions[0] |= (partitionOffsetHead << 8) | (partitionOffsetSector << 16) | (partitionOffsetCylinder << 24) | ((partitionOffsetCylinder >> 8) << 16);
partitions[1] |= (partitionSizeHead << 8) | (partitionSizeSector << 16) | (partitionSizeCylinder << 24) | ((partitionSizeCylinder >> 8) << 16);
}

View File

@ -279,16 +279,29 @@ DEFINE_INTERFACE_STRING(Game2048NewHighScore, "You reached a new high score!");
// Installer.
DEFINE_INTERFACE_STRING(InstallerTitle, SYSTEM_BRAND_SHORT " Installer");
DEFINE_INTERFACE_STRING(InstallerTitle, "Install " SYSTEM_BRAND_SHORT);
DEFINE_INTERFACE_STRING(InstallerDrivesList, "Select the drive to install on:");
DEFINE_INTERFACE_STRING(InstallerDrivesSelectHint, "Choose a drive from the list on the left.");
DEFINE_INTERFACE_STRING(InstallerDriveRemoved, "The drive was disconnected.");
DEFINE_INTERFACE_STRING(InstallerDriveReadOnly, "This drive is read-only. You cannot install " SYSTEM_BRAND_SHORT " on this drive.");
DEFINE_INTERFACE_STRING(InstallerDriveNotEnoughSpace, "This drive does not have enough space to install " SYSTEM_BRAND_SHORT ".");
DEFINE_INTERFACE_STRING(InstallerDriveCouldNotRead, "The drive could not be accessed. It may not be working correctly.");
DEFINE_INTERFACE_STRING(InstallerDriveAlreadyHasPartitions, "The drive already has data on it. To prevent data loss, you cannot install " SYSTEM_BRAND_SHORT " on this drive.");
DEFINE_INTERFACE_STRING(InstallerDriveUnsupported, "This drive uses unsupported features. You cannot install " SYSTEM_BRAND_SHORT " on this drive.");
DEFINE_INTERFACE_STRING(InstallerDriveOkay, SYSTEM_BRAND_SHORT " can be installed on this drive.");
DEFINE_INTERFACE_STRING(InstallerInstall, "Install");
DEFINE_INTERFACE_STRING(InstallerViewLicenses, "Licenses");
DEFINE_INTERFACE_STRING(InstallerGoBack, "Back");
DEFINE_INTERFACE_STRING(InstallerFinish, "Finish");
DEFINE_INTERFACE_STRING(InstallerCustomizeOptions, "Customize your computer.");
DEFINE_INTERFACE_STRING(InstallerCustomizeOptionsHint, "More options will be available in Settings.");
DEFINE_INTERFACE_STRING(InstallerUserName, "User name:");
DEFINE_INTERFACE_STRING(InstallerSystemFont, "System font:");
DEFINE_INTERFACE_STRING(InstallerFontDefault, "Default");
DEFINE_INTERFACE_STRING(InstallerProgressMessage, "Installing, please wait" ELLIPSIS "\nDo not turn off your computer.\nProgress: \aw6]");
DEFINE_INTERFACE_STRING(InstallerCompleteFromOther, "Installation has completed successfully. Remove the installation disk, and restart your computer.");
DEFINE_INTERFACE_STRING(InstallerCompleteFromUSB, "Installation has completed successfully. Disconnect the installation USB, and restart your computer.");
DEFINE_INTERFACE_STRING(InstallerVolumeLabel, "Essence HD");
// TODO System Monitor.

View File

@ -446,7 +446,9 @@ EsBufferReadInt32Endian=444
EsBufferWriteInt32Endian=445
EsSystemGetOptimalWorkQueueThreadCount=446
EsDeviceControl=447
EsWindowGetHandle=448
EsListViewFixedItemRemove=449
EsIconIDFromDriveType=450
EsIconDisplaySetIcon=451
EsFontDatabaseLookupByName=452
_EsWindowGetHandle=453
_EsUISetFont=454

View File

@ -125,9 +125,12 @@ File FileOpen(const char *path, char mode) {
#define Log(...) fprintf(stderr, __VA_ARGS__)
#define EsFileOffset uint64_t
#endif
#include "../shared/hash.cpp"
#include "../shared/partitions.cpp"
#include "build_common.h"
#include "../shared/esfs2.h"
#include "header_generator.c"
@ -1105,16 +1108,7 @@ void Install(const char *driveFile, uint64_t partitionSize, const char *partitio
uint32_t partitions[16] = { 0x80 /* bootable */, 0x83 /* type */, 0x800 /* offset */, (uint32_t) ((partitionSize / 0x200) - 0x800) /* sector count */ };
uint16_t bootSignature = 0xAA55;
uint32_t headsPerCylinder = 256, sectorsPerTrack = 63;
uint32_t partitionOffsetCylinder = (partitions[2] / sectorsPerTrack) / headsPerCylinder;
uint32_t partitionOffsetHead = (partitions[2] / sectorsPerTrack) % headsPerCylinder;
uint32_t partitionOffsetSector = (partitions[2] % sectorsPerTrack) + 1;
uint32_t partitionSizeCylinder = (partitions[3] / sectorsPerTrack) / headsPerCylinder;
uint32_t partitionSizeHead = (partitions[3] / sectorsPerTrack) % headsPerCylinder;
uint32_t partitionSizeSector = (partitions[3] % sectorsPerTrack) + 1;
partitions[0] |= (partitionOffsetHead << 8) | (partitionOffsetSector << 16) | (partitionOffsetCylinder << 24) | ((partitionOffsetCylinder >> 8) << 16);
partitions[1] |= (partitionSizeHead << 8) | (partitionSizeSector << 16) | (partitionSizeCylinder << 24) | ((partitionSizeCylinder >> 8) << 16);
MBRFixPartition(partitions);
FileWrite(f, 64, partitions);
FileWrite(f, 2, &bootSignature);