mirror of https://gitlab.com/nakst/essence
installation progress
This commit is contained in:
parent
f53a980a65
commit
dfd80c3dcd
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -126,6 +126,7 @@ KSpinlock ipiLock;
|
|||
#include <shared/arena.cpp>
|
||||
#else
|
||||
#include <shared/array.cpp>
|
||||
#include <shared/partitions.cpp>
|
||||
#endif
|
||||
|
||||
#include "objects.cpp"
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue