mirror of https://gitlab.com/nakst/essence
finish installer
This commit is contained in:
parent
975f41808d
commit
348f30df4e
|
@ -1,8 +1,3 @@
|
||||||
// TODO Report errors.
|
|
||||||
// TODO GPT support.
|
|
||||||
// TODO Handle crashing?
|
|
||||||
// TODO Write any modified settings during installation.
|
|
||||||
|
|
||||||
#define INSTALLER
|
#define INSTALLER
|
||||||
|
|
||||||
#define ES_CRT_WITHOUT_PREFIX
|
#define ES_CRT_WITHOUT_PREFIX
|
||||||
|
@ -16,8 +11,7 @@
|
||||||
#include <ports/lzma/LzmaDec.c>
|
#include <ports/lzma/LzmaDec.c>
|
||||||
|
|
||||||
#define Log(...)
|
#define Log(...)
|
||||||
// TODO Error handling.
|
#define EsFSError() EsAssert(false)
|
||||||
#define exit(x) EsAssert(false)
|
|
||||||
#include <shared/esfs2.h>
|
#include <shared/esfs2.h>
|
||||||
|
|
||||||
// Assume an additional 64MB of storage capacity is needed on top of totalUncompressedBytes.
|
// Assume an additional 64MB of storage capacity is needed on top of totalUncompressedBytes.
|
||||||
|
@ -27,6 +21,7 @@
|
||||||
|
|
||||||
struct InstallerMetadata {
|
struct InstallerMetadata {
|
||||||
uint64_t totalUncompressedBytes;
|
uint64_t totalUncompressedBytes;
|
||||||
|
uint64_t crc64;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EsStyle styleRoot = {
|
const EsStyle styleRoot = {
|
||||||
|
@ -76,6 +71,8 @@ EsPanel *panelCustomizeOptions;
|
||||||
EsPanel *panelLicenses;
|
EsPanel *panelLicenses;
|
||||||
EsPanel *panelWait;
|
EsPanel *panelWait;
|
||||||
EsPanel *panelComplete;
|
EsPanel *panelComplete;
|
||||||
|
EsPanel *panelError;
|
||||||
|
EsPanel *panelNotSupported;
|
||||||
EsTextbox *userNameTextbox;
|
EsTextbox *userNameTextbox;
|
||||||
EsTextDisplay *progressDisplay;
|
EsTextDisplay *progressDisplay;
|
||||||
const char *cSelectedFont;
|
const char *cSelectedFont;
|
||||||
|
@ -90,6 +87,8 @@ EsFileOffset partitionBytes;
|
||||||
EsUniqueIdentifier installationIdentifier;
|
EsUniqueIdentifier installationIdentifier;
|
||||||
EsMountPoint newFileSystemMountPoint;
|
EsMountPoint newFileSystemMountPoint;
|
||||||
EsHandle mountNewFileSystemEvent;
|
EsHandle mountNewFileSystemEvent;
|
||||||
|
EsError installError;
|
||||||
|
bool archiveCRCError;
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -160,7 +159,7 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
|
||||||
|
|
||||||
e->inFileOffset = sizeof(header);
|
e->inFileOffset = sizeof(header);
|
||||||
|
|
||||||
uint64_t crc64 = 0, actualCRC64 = 0;
|
uint64_t crc64 = 0;
|
||||||
uint64_t totalBytesExtracted = 0;
|
uint64_t totalBytesExtracted = 0;
|
||||||
uint8_t lastProgressByte = 0;
|
uint8_t lastProgressByte = 0;
|
||||||
|
|
||||||
|
@ -169,7 +168,6 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
|
||||||
while (true) {
|
while (true) {
|
||||||
uint64_t fileSize;
|
uint64_t fileSize;
|
||||||
if (!Decompress(e, &fileSize, sizeof(fileSize))) break;
|
if (!Decompress(e, &fileSize, sizeof(fileSize))) break;
|
||||||
actualCRC64 = fileSize;
|
|
||||||
uint16_t nameBytes;
|
uint16_t nameBytes;
|
||||||
if (!Decompress(e, &nameBytes, sizeof(nameBytes))) break;
|
if (!Decompress(e, &nameBytes, sizeof(nameBytes))) break;
|
||||||
if (nameBytes > NAME_MAX - pathOutBytes) break;
|
if (nameBytes > NAME_MAX - pathOutBytes) break;
|
||||||
|
@ -209,46 +207,56 @@ EsError Extract(const char *pathIn, size_t pathInBytes, const char *pathOut, siz
|
||||||
LzmaDec_Free(&e->state, &decompressAllocator);
|
LzmaDec_Free(&e->state, &decompressAllocator);
|
||||||
EsHandleClose(e->fileIn.handle);
|
EsHandleClose(e->fileIn.handle);
|
||||||
|
|
||||||
return crc64 == actualCRC64 ? ES_SUCCESS : ES_ERROR_CORRUPT_DATA;
|
return crc64 == metadata->crc64 ? ES_SUCCESS : ES_ERROR_CORRUPT_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
// TODO Error handling.
|
|
||||||
|
|
||||||
uint64_t writeOffset;
|
uint64_t writeOffset;
|
||||||
uint64_t writeBytes;
|
uint64_t writeBytes;
|
||||||
uint8_t writeBuffer[BUFFER_SIZE];
|
uint8_t writeBuffer[BUFFER_SIZE];
|
||||||
|
EsError formatError = ES_SUCCESS;
|
||||||
|
|
||||||
void FlushWriteBuffer() {
|
bool FlushWriteBuffer() {
|
||||||
if (!writeBytes) return;
|
if (!writeBytes) return true;
|
||||||
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + writeOffset, writeBytes };
|
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + writeOffset, writeBytes };
|
||||||
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, writeBuffer, parameters);
|
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, writeBuffer, parameters);
|
||||||
EsAssert(error == ES_SUCCESS);
|
|
||||||
writeBytes = 0;
|
writeBytes = 0;
|
||||||
|
if (error != ES_SUCCESS) formatError = error;
|
||||||
|
return error == ES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBlock(uint64_t block, uint64_t count, void *buffer) {
|
bool ReadBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
|
if (!FlushWriteBuffer()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + block * blockSize, count * blockSize };
|
EsFileOffset parameters[2] = { partitionOffset * blockDeviceInformation.sectorSize + block * blockSize, count * blockSize };
|
||||||
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_READ, buffer, parameters);
|
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_READ, buffer, parameters);
|
||||||
EsAssert(error == ES_SUCCESS);
|
if (error != ES_SUCCESS) formatError = error;
|
||||||
|
return error == ES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBlock(uint64_t block, uint64_t count, void *buffer) {
|
bool WriteBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
uint64_t offset = block * blockSize, bytes = count * blockSize;
|
uint64_t offset = block * blockSize, bytes = count * blockSize;
|
||||||
|
|
||||||
if (writeBytes && writeOffset + writeBytes == offset && writeBytes + bytes < sizeof(writeBuffer)) {
|
if (writeBytes && writeOffset + writeBytes == offset && writeBytes + bytes < sizeof(writeBuffer)) {
|
||||||
EsMemoryCopy(writeBuffer + writeBytes, buffer, bytes);
|
EsMemoryCopy(writeBuffer + writeBytes, buffer, bytes);
|
||||||
writeBytes += bytes;
|
writeBytes += bytes;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
FlushWriteBuffer();
|
if (!FlushWriteBuffer()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
writeOffset = offset;
|
writeOffset = offset;
|
||||||
writeBytes = bytes;
|
writeBytes = bytes;
|
||||||
EsMemoryCopy(writeBuffer, buffer, bytes);
|
EsMemoryCopy(writeBuffer, buffer, bytes);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBytes(uint64_t byteOffset, uint64_t byteCount, void *buffer) {
|
bool WriteBytes(uint64_t byteOffset, uint64_t byteCount, void *buffer) {
|
||||||
uint64_t firstSector = byteOffset / blockDeviceInformation.sectorSize;
|
uint64_t firstSector = byteOffset / blockDeviceInformation.sectorSize;
|
||||||
uint64_t lastSector = (byteOffset + byteCount - 1) / blockDeviceInformation.sectorSize;
|
uint64_t lastSector = (byteOffset + byteCount - 1) / blockDeviceInformation.sectorSize;
|
||||||
uint64_t sectorCount = lastSector - firstSector + 1;
|
uint64_t sectorCount = lastSector - firstSector + 1;
|
||||||
|
@ -259,16 +267,25 @@ void WriteBytes(uint64_t byteOffset, uint64_t byteCount, void *buffer) {
|
||||||
if (i > 0 && i < sectorCount - 1) continue;
|
if (i > 0 && i < sectorCount - 1) continue;
|
||||||
EsFileOffset parameters[2] = { (partitionOffset + firstSector + i) * blockDeviceInformation.sectorSize, blockDeviceInformation.sectorSize } ;
|
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);
|
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_READ, (uint8_t *) buffer2 + i * blockDeviceInformation.sectorSize, parameters);
|
||||||
EsAssert(error == ES_SUCCESS);
|
|
||||||
|
if (error != ES_SUCCESS) {
|
||||||
|
formatError = error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EsMemoryCopy((uint8_t *) buffer2 + byteOffset % blockDeviceInformation.sectorSize, buffer, byteCount);
|
EsMemoryCopy((uint8_t *) buffer2 + byteOffset % blockDeviceInformation.sectorSize, buffer, byteCount);
|
||||||
|
|
||||||
EsFileOffset parameters[2] = { (partitionOffset + firstSector) * blockDeviceInformation.sectorSize, sectorCount * blockDeviceInformation.sectorSize };
|
EsFileOffset parameters[2] = { (partitionOffset + firstSector) * blockDeviceInformation.sectorSize, sectorCount * blockDeviceInformation.sectorSize };
|
||||||
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, buffer, parameters);
|
EsError error = EsDeviceControl(driveHandle, ES_DEVICE_CONTROL_BLOCK_WRITE, buffer, parameters);
|
||||||
EsAssert(error == ES_SUCCESS);
|
|
||||||
|
if (error != ES_SUCCESS) {
|
||||||
|
formatError = error;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EsHeapFree(buffer2);
|
EsHeapFree(buffer2);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
@ -828,6 +845,10 @@ EsError Install() {
|
||||||
Format(partitionBytes, interfaceString_InstallerVolumeLabel, installationIdentifier, kernel, kernelBytes);
|
Format(partitionBytes, interfaceString_InstallerVolumeLabel, installationIdentifier, kernel, kernelBytes);
|
||||||
FlushWriteBuffer();
|
FlushWriteBuffer();
|
||||||
|
|
||||||
|
if (formatError != ES_SUCCESS) {
|
||||||
|
return formatError;
|
||||||
|
}
|
||||||
|
|
||||||
m.user.context1.u = 8;
|
m.user.context1.u = 8;
|
||||||
EsMessagePost(nullptr, &m);
|
EsMessagePost(nullptr, &m);
|
||||||
|
|
||||||
|
@ -843,22 +864,60 @@ EsError Install() {
|
||||||
}
|
}
|
||||||
|
|
||||||
error = Extract(EsLiteral("0:/installer_archive.dat"), newFileSystemMountPoint.prefix, newFileSystemMountPoint.prefixBytes);
|
error = Extract(EsLiteral("0:/installer_archive.dat"), newFileSystemMountPoint.prefix, newFileSystemMountPoint.prefixBytes);
|
||||||
if (error != ES_SUCCESS) return error;
|
|
||||||
|
if (error == ES_ERROR_CORRUPT_DATA) {
|
||||||
|
archiveCRCError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != ES_SUCCESS) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
return ES_SUCCESS;
|
return ES_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallThread(EsGeneric) {
|
void InstallThread(EsGeneric) {
|
||||||
EsPerformanceTimerPush();
|
EsPerformanceTimerPush();
|
||||||
EsError error = Install();
|
installError = Install();
|
||||||
EsAssert(error == ES_SUCCESS); // TODO Reporting errors.
|
EsPrint("Installation finished in %Fs. Extracted %D from the archive. Error code = %d.\n", EsPerformanceTimerPop(), metadata->totalUncompressedBytes, installError);
|
||||||
EsPrint("Installation finished in %Fs. Extracted %D from the archive.\n", EsPerformanceTimerPop(), metadata->totalUncompressedBytes);
|
|
||||||
|
|
||||||
EsMessage m = { MSG_SET_PROGRESS };
|
EsMessage m = { MSG_SET_PROGRESS };
|
||||||
m.user.context1.u = 100;
|
m.user.context1.u = 100;
|
||||||
EsMessagePost(nullptr, &m);
|
EsMessagePost(nullptr, &m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteNewConfiguration() {
|
||||||
|
size_t newSystemConfigurationPathBytes, newSystemConfigurationBytes;
|
||||||
|
char *newSystemConfigurationPath = EsStringAllocateAndFormat(&newSystemConfigurationPathBytes, "%s/Essence/Default.ini",
|
||||||
|
newFileSystemMountPoint.prefixBytes, newFileSystemMountPoint.prefix);
|
||||||
|
char *newSystemConfiguration = (char *) EsFileReadAll(newSystemConfigurationPath, newSystemConfigurationPathBytes, &newSystemConfigurationBytes);
|
||||||
|
|
||||||
|
size_t lineBufferBytes = 4096;
|
||||||
|
char *lineBuffer = (char *) EsHeapAllocate(lineBufferBytes, false);
|
||||||
|
EsINIState s = { .buffer = newSystemConfiguration, .bytes = newSystemConfigurationBytes };
|
||||||
|
EsBuffer buffer = { .canGrow = true };
|
||||||
|
|
||||||
|
while (EsINIParse(&s)) {
|
||||||
|
if (!s.sectionClassBytes && 0 == EsStringCompareRaw(s.section, s.sectionBytes, EsLiteral("ui"))
|
||||||
|
&& 0 == EsStringCompareRaw(s.key, s.keyBytes, EsLiteral("font_sans"))) {
|
||||||
|
EsBufferFormat(&buffer, "font_sans=%z\n", cSelectedFont);
|
||||||
|
} else if (!s.sectionClassBytes && 0 == EsStringCompareRaw(s.section, s.sectionBytes, EsLiteral("general"))
|
||||||
|
&& 0 == EsStringCompareRaw(s.key, s.keyBytes, EsLiteral("installation_state"))) {
|
||||||
|
EsBufferFormat(&buffer, "installation_state=0\n");
|
||||||
|
} else {
|
||||||
|
size_t lineBytes = EsINIFormat(&s, lineBuffer, lineBufferBytes);
|
||||||
|
EsBufferWrite(&buffer, lineBuffer, lineBytes);
|
||||||
|
EsAssert(lineBytes < lineBufferBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EsFileWriteAll(newSystemConfigurationPath, newSystemConfigurationPathBytes, buffer.out, buffer.position);
|
||||||
|
|
||||||
|
EsHeapFree(newSystemConfigurationPath);
|
||||||
|
EsHeapFree(buffer.out);
|
||||||
|
EsHeapFree(lineBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|
||||||
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
|
void ButtonViewLicenses(EsInstance *, EsElement *, EsCommand *) {
|
||||||
|
@ -894,9 +953,35 @@ void ButtonFont(EsInstance *, EsElement *element, EsCommand *) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Complete() {
|
||||||
|
if (installError == ES_SUCCESS) {
|
||||||
|
WriteNewConfiguration();
|
||||||
|
EsPanelSwitchTo(switcher, panelComplete, ES_TRANSITION_FADE_IN);
|
||||||
|
} else {
|
||||||
|
EsPanel *row = EsPanelCreate(panelError, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
|
||||||
|
EsIconDisplayCreate(row, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_ERROR);
|
||||||
|
EsSpacerCreate(row, ES_FLAGS_DEFAULT, 0, 15, 0);
|
||||||
|
|
||||||
|
if (installError == ES_ERROR_INSUFFICIENT_RESOURCES) {
|
||||||
|
EsTextDisplayCreate(row, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerFailedResources));
|
||||||
|
} else if (archiveCRCError) {
|
||||||
|
EsTextDisplayCreate(row, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerFailedArchiveCRCError));
|
||||||
|
} else {
|
||||||
|
EsTextDisplayCreate(row, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerFailedGeneric));
|
||||||
|
}
|
||||||
|
|
||||||
|
EsSpacerCreate(panelError, ES_CELL_FILL);
|
||||||
|
EsPanel *buttonsRow = EsPanelCreate(panelError, 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);
|
||||||
|
|
||||||
|
EsPanelSwitchTo(switcher, panelError, ES_TRANSITION_FADE_IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ButtonFinish(EsInstance *, EsElement *, EsCommand *) {
|
void ButtonFinish(EsInstance *, EsElement *, EsCommand *) {
|
||||||
if (progress == 100) {
|
if (progress == 100) {
|
||||||
EsPanelSwitchTo(switcher, panelComplete, ES_TRANSITION_FADE_IN);
|
Complete();
|
||||||
} else {
|
} else {
|
||||||
onWaitScreen = true;
|
onWaitScreen = true;
|
||||||
EsPanelSwitchTo(switcher, panelWait, ES_TRANSITION_FADE_IN);
|
EsPanelSwitchTo(switcher, panelWait, ES_TRANSITION_FADE_IN);
|
||||||
|
@ -960,7 +1045,6 @@ void _start() {
|
||||||
|
|
||||||
{
|
{
|
||||||
panelInstallOptions = EsPanelCreate(switcher, ES_CELL_H_FILL, &styleRoot);
|
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));
|
EsTextDisplayCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
||||||
|
|
||||||
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
|
EsPanel *drivesPanel = EsPanelCreate(panelInstallOptions, ES_CELL_H_FILL, ES_STYLE_PANEL_INSET);
|
||||||
|
@ -1049,14 +1133,45 @@ void _start() {
|
||||||
EsTextDisplayCreate(panelComplete, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerCompleteFromOther));
|
EsTextDisplayCreate(panelComplete, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerCompleteFromOther));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Failure messages.
|
|
||||||
|
|
||||||
EsSpacerCreate(panelComplete, ES_CELL_FILL);
|
EsSpacerCreate(panelComplete, ES_CELL_FILL);
|
||||||
EsPanel *buttonsRow = EsPanelCreate(panelComplete, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
|
EsPanel *buttonsRow = EsPanelCreate(panelComplete, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL, &styleButtonsRow);
|
||||||
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
|
EsSpacerCreate(buttonsRow, ES_CELL_H_FILL);
|
||||||
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopRestartAction)), ButtonRestart);
|
EsButtonOnCommand(EsButtonCreate(buttonsRow, ES_FLAGS_DEFAULT, 0, INTERFACE_STRING(DesktopRestartAction)), ButtonRestart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
panelError = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
|
||||||
|
EsTextDisplayCreate(panelError, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
||||||
|
// Contents is created in Complete().
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
panelNotSupported = EsPanelCreate(switcher, ES_CELL_FILL, &styleRoot);
|
||||||
|
EsTextDisplayCreate(panelNotSupported, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0, INTERFACE_STRING(InstallerTitle));
|
||||||
|
|
||||||
|
EsPanel *row = EsPanelCreate(panelNotSupported, ES_CELL_H_FILL | ES_PANEL_HORIZONTAL);
|
||||||
|
EsIconDisplayCreate(row, ES_FLAGS_DEFAULT, 0, ES_ICON_DIALOG_ERROR);
|
||||||
|
EsSpacerCreate(row, ES_FLAGS_DEFAULT, 0, 15, 0);
|
||||||
|
|
||||||
|
EsTextDisplayCreate(row, ES_CELL_H_FILL, ES_STYLE_TEXT_PARAGRAPH, INTERFACE_STRING(InstallerNotSupported));
|
||||||
|
|
||||||
|
EsSpacerCreate(panelNotSupported, ES_CELL_FILL);
|
||||||
|
EsPanel *buttonsRow = EsPanelCreate(panelNotSupported, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MemoryAvailable available;
|
||||||
|
EsSyscall(ES_SYSCALL_MEMORY_GET_AVAILABLE, (uintptr_t) &available, 0, 0, 0);
|
||||||
|
|
||||||
|
if (available.total < 64 * 1024 * 1024) {
|
||||||
|
EsPanelSwitchTo(switcher, panelNotSupported, ES_TRANSITION_NONE);
|
||||||
|
} else {
|
||||||
|
EsPanelSwitchTo(switcher, panelInstallOptions, ES_TRANSITION_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
|
EsDeviceEnumerate([] (EsMessageDevice device, EsGeneric) {
|
||||||
ConnectedDriveAdd(device);
|
ConnectedDriveAdd(device);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
@ -1101,7 +1216,7 @@ void _start() {
|
||||||
|
|
||||||
if (onWaitScreen && progress == 100) {
|
if (onWaitScreen && progress == 100) {
|
||||||
onWaitScreen = false;
|
onWaitScreen = false;
|
||||||
EsPanelSwitchTo(switcher, panelComplete, ES_TRANSITION_FADE_IN);
|
Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1654,6 +1654,12 @@ void ApplicationInstanceCrashed(EsMessage *message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
application->singleInstance = nullptr;
|
application->singleInstance = nullptr;
|
||||||
|
|
||||||
|
if (desktop.installationState == INSTALLATION_STATE_INSTALLER && desktop.installer == application) {
|
||||||
|
// Restart the installer.
|
||||||
|
ApplicationInstanceCreate(desktop.installer->id, nullptr, nullptr, true /* hidden */);
|
||||||
|
}
|
||||||
|
|
||||||
ApplicationTemporaryDestroy(application);
|
ApplicationTemporaryDestroy(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -762,6 +762,7 @@ enum EsSyscallType {
|
||||||
ES_SYSCALL_MEMORY_OPEN
|
ES_SYSCALL_MEMORY_OPEN
|
||||||
ES_SYSCALL_MEMORY_COMMIT
|
ES_SYSCALL_MEMORY_COMMIT
|
||||||
ES_SYSCALL_MEMORY_FAULT_RANGE
|
ES_SYSCALL_MEMORY_FAULT_RANGE
|
||||||
|
ES_SYSCALL_MEMORY_GET_AVAILABLE
|
||||||
|
|
||||||
// Processing.
|
// Processing.
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,11 @@ struct BundleFile {
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MemoryAvailable {
|
||||||
|
size_t available;
|
||||||
|
size_t total;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
#define K_BOOT_DRIVE ""
|
#define K_BOOT_DRIVE ""
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -217,6 +217,15 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_FAULT_RANGE) {
|
||||||
SYSCALL_RETURN(success ? ES_SUCCESS : ES_FATAL_ERROR_INVALID_BUFFER, !success);
|
SYSCALL_RETURN(success ? ES_SUCCESS : ES_FATAL_ERROR_INVALID_BUFFER, !success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_GET_AVAILABLE) {
|
||||||
|
MemoryAvailable available;
|
||||||
|
EsMemoryZero(&available, sizeof(MemoryAvailable));
|
||||||
|
available.available = MM_REMAINING_COMMIT() * K_PAGE_SIZE;
|
||||||
|
available.total = pmm.commitLimit * K_PAGE_SIZE;
|
||||||
|
SYSCALL_WRITE(argument0, &available, sizeof(MemoryAvailable));
|
||||||
|
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||||
|
}
|
||||||
|
|
||||||
SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
|
SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
|
||||||
EsProcessCreationArguments arguments;
|
EsProcessCreationArguments arguments;
|
||||||
SYSCALL_READ(&arguments, argument0, sizeof(EsProcessCreationArguments));
|
SYSCALL_READ(&arguments, argument0, sizeof(EsProcessCreationArguments));
|
||||||
|
|
240
shared/esfs2.h
240
shared/esfs2.h
|
@ -267,23 +267,32 @@ Superblock superblock;
|
||||||
GroupDescriptor *groupDescriptorTable;
|
GroupDescriptor *groupDescriptorTable;
|
||||||
uint64_t copiedCount;
|
uint64_t copiedCount;
|
||||||
|
|
||||||
void ReadBlock(uint64_t block, uint64_t count, void *buffer);
|
bool ReadBlock(uint64_t block, uint64_t count, void *buffer);
|
||||||
void WriteBlock(uint64_t block, uint64_t count, void *buffer);
|
bool WriteBlock(uint64_t block, uint64_t count, void *buffer);
|
||||||
void WriteBytes(uint64_t offset, uint64_t count, void *buffer);
|
bool WriteBytes(uint64_t offset, uint64_t count, void *buffer);
|
||||||
|
|
||||||
void ReadDirectoryEntryReference(DirectoryEntryReference reference, DirectoryEntry *entry) {
|
bool ReadDirectoryEntryReference(DirectoryEntryReference reference, DirectoryEntry *entry) {
|
||||||
uint8_t buffer[superblock.blockSize];
|
uint8_t buffer[superblock.blockSize];
|
||||||
ReadBlock(reference.block, 1, buffer);
|
|
||||||
|
if (!ReadBlock(reference.block, 1, buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(entry, buffer + reference.offsetIntoBlock, sizeof(DirectoryEntry));
|
memcpy(entry, buffer + reference.offsetIntoBlock, sizeof(DirectoryEntry));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteDirectoryEntryReference(DirectoryEntryReference reference, DirectoryEntry *entry) {
|
bool WriteDirectoryEntryReference(DirectoryEntryReference reference, DirectoryEntry *entry) {
|
||||||
entry->checksum = 0;
|
entry->checksum = 0;
|
||||||
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
||||||
uint8_t buffer[superblock.blockSize];
|
uint8_t buffer[superblock.blockSize];
|
||||||
ReadBlock(reference.block, 1, buffer);
|
|
||||||
memcpy(buffer + reference.offsetIntoBlock, entry, sizeof(DirectoryEntry));
|
if (ReadBlock(reference.block, 1, buffer)) {
|
||||||
WriteBlock(reference.block, 1, buffer);
|
memcpy(buffer + reference.offsetIntoBlock, entry, sizeof(DirectoryEntry));
|
||||||
|
return WriteBlock(reference.block, 1, buffer);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute *FindAttribute(DirectoryEntry *entry, uint16_t type) {
|
Attribute *FindAttribute(DirectoryEntry *entry, uint16_t type) {
|
||||||
|
@ -295,7 +304,7 @@ Attribute *FindAttribute(DirectoryEntry *entry, uint16_t type) {
|
||||||
|
|
||||||
if (count++ == entry->attributeCount) {
|
if (count++ == entry->attributeCount) {
|
||||||
Log("Could not find attribute %d.\n", type);
|
Log("Could not find attribute %d.\n", type);
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +355,7 @@ IndexKey *InsertKeyIntoVertex(uint64_t newKey, IndexVertex *vertex) {
|
||||||
return insertionPosition;
|
return insertionPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AllocateExtent(uint64_t increaseBlocks, uint64_t *extentStart, uint64_t *extentCount) {
|
bool AllocateExtent(uint64_t increaseBlocks, uint64_t *extentStart, uint64_t *extentCount) {
|
||||||
// Log("used %ld/%ld, need %ld more\n", superblock.blocksUsed, superblock.blockCount, increaseBlocks);
|
// Log("used %ld/%ld, need %ld more\n", superblock.blocksUsed, superblock.blockCount, increaseBlocks);
|
||||||
|
|
||||||
// Find a group to allocate the next extent from.
|
// Find a group to allocate the next extent from.
|
||||||
|
@ -373,7 +382,7 @@ void AllocateExtent(uint64_t increaseBlocks, uint64_t *extentStart, uint64_t *ex
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
Log("Out of space.\n");
|
Log("Out of space.\n");
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the bitmap, find the largest extent, and mark it as in use.
|
// Load the bitmap, find the largest extent, and mark it as in use.
|
||||||
|
@ -382,7 +391,9 @@ void AllocateExtent(uint64_t increaseBlocks, uint64_t *extentStart, uint64_t *ex
|
||||||
|
|
||||||
{
|
{
|
||||||
if (target->blockBitmap) {
|
if (target->blockBitmap) {
|
||||||
ReadBlock(target->blockBitmap, superblock.blocksPerGroupBlockBitmap, bitmap);
|
if (!ReadBlock(target->blockBitmap, superblock.blocksPerGroupBlockBitmap, bitmap)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
memset(bitmap, 0, superblock.blocksPerGroupBlockBitmap * superblock.blockSize);
|
memset(bitmap, 0, superblock.blocksPerGroupBlockBitmap * superblock.blockSize);
|
||||||
for (uint64_t i = 0; i < superblock.blocksPerGroupBlockBitmap; i++) bitmap[i / 8] |= 1 << (i % 8);
|
for (uint64_t i = 0; i < superblock.blocksPerGroupBlockBitmap; i++) bitmap[i / 8] |= 1 << (i % 8);
|
||||||
|
@ -453,25 +464,28 @@ void AllocateExtent(uint64_t increaseBlocks, uint64_t *extentStart, uint64_t *ex
|
||||||
target->checksum = 0;
|
target->checksum = 0;
|
||||||
target->checksum = CalculateCRC32(target, sizeof(GroupDescriptor), 0);
|
target->checksum = CalculateCRC32(target, sizeof(GroupDescriptor), 0);
|
||||||
|
|
||||||
WriteBlock(target->blockBitmap, superblock.blocksPerGroupBlockBitmap, bitmap);
|
if (!WriteBlock(target->blockBitmap, superblock.blocksPerGroupBlockBitmap, bitmap)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*extentStart = *extentStart + (target - groupDescriptorTable) * superblock.blocksPerGroup;
|
*extentStart = *extentStart + (target - groupDescriptorTable) * superblock.blocksPerGroup;
|
||||||
superblock.blocksUsed += *extentCount;
|
superblock.blocksUsed += *extentCount;
|
||||||
// Log("allocate extent: %ld -> %ld (for %ld)\n", extentStart, extentStart + extentCount, increaseBlocks);
|
// Log("allocate extent: %ld -> %ld (for %ld)\n", extentStart, extentStart + extentCount, increaseBlocks);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccessNode(DirectoryEntry *node, void *buffer, uint64_t offsetIntoFile, uint64_t totalCount, DirectoryEntryReference *reference, bool read) {
|
bool AccessNode(DirectoryEntry *node, void *buffer, uint64_t offsetIntoFile, uint64_t totalCount, DirectoryEntryReference *reference, bool read) {
|
||||||
if (!totalCount) return;
|
if (!totalCount) return true;
|
||||||
AttributeData *dataAttribute = (AttributeData *) FindAttribute(node, ESFS_ATTRIBUTE_DATA);
|
AttributeData *dataAttribute = (AttributeData *) FindAttribute(node, ESFS_ATTRIBUTE_DATA);
|
||||||
|
|
||||||
if (dataAttribute->indirection == ESFS_INDIRECTION_DIRECT && read) {
|
if (dataAttribute->indirection == ESFS_INDIRECTION_DIRECT && read) {
|
||||||
memcpy(buffer, dataAttribute->data + offsetIntoFile, totalCount);
|
memcpy(buffer, dataAttribute->data + offsetIntoFile, totalCount);
|
||||||
return;
|
return true;
|
||||||
} else if (dataAttribute->indirection == ESFS_INDIRECTION_DIRECT && !read) {
|
} else if (dataAttribute->indirection == ESFS_INDIRECTION_DIRECT && !read) {
|
||||||
assert(!reference);
|
assert(!reference);
|
||||||
memcpy(dataAttribute->data + offsetIntoFile, buffer, totalCount);
|
memcpy(dataAttribute->data + offsetIntoFile, buffer, totalCount);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(dataAttribute->indirection == ESFS_INDIRECTION_L1);
|
assert(dataAttribute->indirection == ESFS_INDIRECTION_L1);
|
||||||
|
@ -521,14 +535,19 @@ void AccessNode(DirectoryEntry *node, void *buffer, uint64_t offsetIntoFile, uin
|
||||||
uint8_t blockBuffer[superblock.blockSize];
|
uint8_t blockBuffer[superblock.blockSize];
|
||||||
|
|
||||||
if (read || count != superblock.blockSize) {
|
if (read || count != superblock.blockSize) {
|
||||||
ReadBlock(block, 1, blockBuffer);
|
if (!ReadBlock(block, 1, blockBuffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read) {
|
if (read) {
|
||||||
memcpy(buffer, blockBuffer + offset, count);
|
memcpy(buffer, blockBuffer + offset, count);
|
||||||
} else {
|
} else {
|
||||||
memcpy(blockBuffer + offset, buffer, count);
|
memcpy(blockBuffer + offset, buffer, count);
|
||||||
WriteBlock(block, 1, blockBuffer);
|
|
||||||
|
if (!WriteBlock(block, 1, blockBuffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reference) {
|
if (reference) {
|
||||||
|
@ -543,9 +562,11 @@ void AccessNode(DirectoryEntry *node, void *buffer, uint64_t offsetIntoFile, uin
|
||||||
buffer = (uint8_t *) buffer + count;
|
buffer = (uint8_t *) buffer + count;
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
bool ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
||||||
assert(newSize >= entry->fileSize);
|
assert(newSize >= entry->fileSize);
|
||||||
|
|
||||||
AttributeData *dataAttribute = (AttributeData *) FindAttribute(entry, ESFS_ATTRIBUTE_DATA);
|
AttributeData *dataAttribute = (AttributeData *) FindAttribute(entry, ESFS_ATTRIBUTE_DATA);
|
||||||
|
@ -553,7 +574,7 @@ void ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
||||||
if (newSize < (uint64_t) (dataAttribute->size - dataAttribute->dataOffset) && entry->nodeType == ESFS_NODE_TYPE_FILE) {
|
if (newSize < (uint64_t) (dataAttribute->size - dataAttribute->dataOffset) && entry->nodeType == ESFS_NODE_TYPE_FILE) {
|
||||||
dataAttribute->indirection = ESFS_INDIRECTION_DIRECT;
|
dataAttribute->indirection = ESFS_INDIRECTION_DIRECT;
|
||||||
dataAttribute->count = entry->fileSize = newSize;
|
dataAttribute->count = entry->fileSize = newSize;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log("\tresize to %lu\n", newSize);
|
// Log("\tresize to %lu\n", newSize);
|
||||||
|
@ -588,7 +609,9 @@ void ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
||||||
uint64_t extentStart, extentCount, encodedLength;
|
uint64_t extentStart, extentCount, encodedLength;
|
||||||
uint8_t encode[32];
|
uint8_t encode[32];
|
||||||
|
|
||||||
AllocateExtent(increaseBlocks, &extentStart, &extentCount);
|
if (!AllocateExtent(increaseBlocks, &extentStart, &extentCount)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (extentStart == previousExtentStart + previousExtentCount) {
|
if (extentStart == previousExtentStart + previousExtentCount) {
|
||||||
dataAttribute->count--;
|
dataAttribute->count--;
|
||||||
|
@ -604,7 +627,7 @@ void ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
||||||
|
|
||||||
if (offsetIntoExtentList + encodedLength > (uint64_t) (dataAttribute->size - dataAttribute->dataOffset)) {
|
if (offsetIntoExtentList + encodedLength > (uint64_t) (dataAttribute->size - dataAttribute->dataOffset)) {
|
||||||
Log("Unimplemented - indirection past L1.\n");
|
Log("Unimplemented - indirection past L1.\n");
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(extents + offsetIntoExtentList, encode, encodedLength);
|
memcpy(extents + offsetIntoExtentList, encode, encodedLength);
|
||||||
|
@ -615,8 +638,10 @@ void ResizeNode(DirectoryEntry *entry, uint64_t newSize) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log("Unimplemented - node truncation.\n");
|
Log("Unimplemented - node truncation.\n");
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -702,7 +727,7 @@ void NewDirectoryEntry(DirectoryEntry *entry, uint8_t nodeType, EsUniqueIdentifi
|
||||||
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, DirectoryEntryReference *outputReference,
|
bool AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, DirectoryEntryReference *outputReference,
|
||||||
DirectoryEntryReference directoryReference) {
|
DirectoryEntryReference directoryReference) {
|
||||||
// Log("add %s to %s\n", name, path);
|
// Log("add %s to %s\n", name, path);
|
||||||
|
|
||||||
|
@ -710,7 +735,7 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
|
|
||||||
DirectoryEntry directory;
|
DirectoryEntry directory;
|
||||||
|
|
||||||
ReadDirectoryEntryReference(directoryReference, &directory);
|
if (!ReadDirectoryEntryReference(directoryReference, &directory)) return false;
|
||||||
AttributeData *dataAttribute = (AttributeData *) FindAttribute(&directory, ESFS_ATTRIBUTE_DATA);
|
AttributeData *dataAttribute = (AttributeData *) FindAttribute(&directory, ESFS_ATTRIBUTE_DATA);
|
||||||
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
|
@ -720,12 +745,15 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
|
|
||||||
if (!(directoryAttribute->childNodes % superblock.directoryEntriesPerBlock)) {
|
if (!(directoryAttribute->childNodes % superblock.directoryEntriesPerBlock)) {
|
||||||
// Log("increasing directory to fit %ld entries\n========={\n", (directory.fileSize + superblock.blockSize) / sizeof(DirectoryEntry));
|
// Log("increasing directory to fit %ld entries\n========={\n", (directory.fileSize + superblock.blockSize) / sizeof(DirectoryEntry));
|
||||||
ResizeNode(&directory, directory.fileSize + superblock.blockSize);
|
if (!ResizeNode(&directory, directory.fileSize + superblock.blockSize)) return false;
|
||||||
// Log("========}\n");
|
// Log("========}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
directoryAttribute->childNodes++;
|
directoryAttribute->childNodes++;
|
||||||
WriteDirectoryEntryReference(directoryReference, &directory);
|
|
||||||
|
if (!WriteDirectoryEntryReference(directoryReference, &directory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Create the directory entry, and write it to the directory.
|
// Step 2: Create the directory entry, and write it to the directory.
|
||||||
|
@ -736,7 +764,10 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
{
|
{
|
||||||
NewDirectoryEntry(&entry, nodeType, directory.identifier, name);
|
NewDirectoryEntry(&entry, nodeType, directory.identifier, name);
|
||||||
// Log("\tchild nodes: %ld\n", directoryAttribute->childNodes);
|
// Log("\tchild nodes: %ld\n", directoryAttribute->childNodes);
|
||||||
AccessNode(&directory, &entry, (directoryAttribute->childNodes - 1) * sizeof(DirectoryEntry), sizeof(DirectoryEntry), &reference, false);
|
|
||||||
|
if (!AccessNode(&directory, &entry, (directoryAttribute->childNodes - 1) * sizeof(DirectoryEntry), sizeof(DirectoryEntry), &reference, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Add the node into the index.
|
// Step 3: Add the node into the index.
|
||||||
|
@ -756,14 +787,20 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
// Directory is empty - create the root vertex.
|
// Directory is empty - create the root vertex.
|
||||||
|
|
||||||
uint64_t _unused;
|
uint64_t _unused;
|
||||||
AllocateExtent(1, &directoryAttribute->indexRootBlock, &_unused);
|
|
||||||
|
if (!AllocateExtent(1, &directoryAttribute->indexRootBlock, &_unused)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
blocks[0] = directoryAttribute->indexRootBlock;
|
blocks[0] = directoryAttribute->indexRootBlock;
|
||||||
vertex->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
vertex->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
||||||
vertex->offset = ESFS_INDEX_KEY_OFFSET;
|
vertex->offset = ESFS_INDEX_KEY_OFFSET;
|
||||||
memcpy(vertex->signature, ESFS_INDEX_VERTEX_SIGNATURE, 4);
|
memcpy(vertex->signature, ESFS_INDEX_VERTEX_SIGNATURE, 4);
|
||||||
// Log("rootBlock = %ld for %s\n", directoryAttribute->indexRootBlock, path);
|
// Log("rootBlock = %ld for %s\n", directoryAttribute->indexRootBlock, path);
|
||||||
} else {
|
} else {
|
||||||
ReadBlock(blocks[0], 1, vertex);
|
if (!ReadBlock(blocks[0], 1, vertex)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Log("start = %ld for %s\n", blocks[0], path);
|
// Log("start = %ld for %s\n", blocks[0], path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,7 +809,7 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
if (ESFS_VERTEX_KEY(vertex, i)->value == newKey) {
|
if (ESFS_VERTEX_KEY(vertex, i)->value == newKey) {
|
||||||
// The key is already in the tree.
|
// The key is already in the tree.
|
||||||
Log("The file already exists.");
|
Log("The file already exists.");
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,7 +818,11 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
|
|
||||||
if ((i == vertex->count || newKey < key->value) && key->child) {
|
if ((i == vertex->count || newKey < key->value) && key->child) {
|
||||||
blocks[++depth] = key->child;
|
blocks[++depth] = key->child;
|
||||||
ReadBlock(key->child, 1, vertex);
|
|
||||||
|
if (!ReadBlock(key->child, 1, vertex)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,7 +850,7 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
// Create a new sibling.
|
// Create a new sibling.
|
||||||
|
|
||||||
uint64_t siblingBlock = 0, _unused;
|
uint64_t siblingBlock = 0, _unused;
|
||||||
AllocateExtent(1, &siblingBlock, &_unused);
|
if (!AllocateExtent(1, &siblingBlock, &_unused)) return false;
|
||||||
IndexVertex *sibling = (IndexVertex *) _buffer0;
|
IndexVertex *sibling = (IndexVertex *) _buffer0;
|
||||||
sibling->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
sibling->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
||||||
sibling->offset = ESFS_INDEX_KEY_OFFSET;
|
sibling->offset = ESFS_INDEX_KEY_OFFSET;
|
||||||
|
@ -829,7 +870,7 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
uint64_t _unused;
|
uint64_t _unused;
|
||||||
AllocateExtent(1, &blocks[0], &_unused);
|
if (!AllocateExtent(1, &blocks[0], &_unused)) return false;
|
||||||
|
|
||||||
parent->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
parent->maxCount = (superblock.blockSize - ESFS_INDEX_KEY_OFFSET) / sizeof(IndexKey) - 1 /* +1 key */;
|
||||||
parent->offset = ESFS_INDEX_KEY_OFFSET;
|
parent->offset = ESFS_INDEX_KEY_OFFSET;
|
||||||
|
@ -841,7 +882,9 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
parent->keys[0].child = blocks[1];
|
parent->keys[0].child = blocks[1];
|
||||||
directoryAttribute->indexRootBlock = blocks[0];
|
directoryAttribute->indexRootBlock = blocks[0];
|
||||||
} else {
|
} else {
|
||||||
ReadBlock(blocks[depth - 1], 1, parent);
|
if (!ReadBlock(blocks[depth - 1], 1, parent)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexKey *parentKeys = (IndexKey *) ((uint8_t *) parent + parent->offset);
|
IndexKey *parentKeys = (IndexKey *) ((uint8_t *) parent + parent->offset);
|
||||||
|
@ -886,8 +929,8 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
|
|
||||||
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock.blockSize, 0);
|
sibling->checksum = 0; sibling->checksum = CalculateCRC32(sibling, superblock.blockSize, 0);
|
||||||
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock.blockSize, 0);
|
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock.blockSize, 0);
|
||||||
WriteBlock(siblingBlock, 1, sibling);
|
if (!WriteBlock(siblingBlock, 1, sibling)) return false;
|
||||||
WriteBlock(blocks[depth], 1, vertex);
|
if (!WriteBlock(blocks[depth], 1, vertex)) return false;
|
||||||
|
|
||||||
// Check if the parent vertex is full.
|
// Check if the parent vertex is full.
|
||||||
|
|
||||||
|
@ -898,33 +941,49 @@ void AddNode(const char *name, uint8_t nodeType, DirectoryEntry *outputEntry, Di
|
||||||
// Write the block.
|
// Write the block.
|
||||||
|
|
||||||
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock.blockSize, 0);
|
vertex->checksum = 0; vertex->checksum = CalculateCRC32(vertex, superblock.blockSize, 0);
|
||||||
WriteBlock(blocks[depth], 1, vertex);
|
if (!WriteBlock(blocks[depth], 1, vertex)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outputEntry) *outputEntry = entry;
|
if (outputEntry) *outputEntry = entry;
|
||||||
if (outputReference) *outputReference = reference;
|
if (outputReference) *outputReference = reference;
|
||||||
|
|
||||||
// PrintTree(directoryAttribute->indexRootBlock);
|
// PrintTree(directoryAttribute->indexRootBlock);
|
||||||
WriteDirectoryEntryReference(directoryReference, &directory);
|
if (!WriteDirectoryEntryReference(directoryReference, &directory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MountVolume() {
|
bool MountVolume() {
|
||||||
// Read the superblock.
|
// Read the superblock.
|
||||||
blockSize = ESFS_BOOT_SUPER_BLOCK_SIZE;
|
blockSize = ESFS_BOOT_SUPER_BLOCK_SIZE;
|
||||||
ReadBlock(1, 1, &superblock);
|
|
||||||
|
if (!ReadBlock(1, 1, &superblock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (superblock.mounted) {
|
if (superblock.mounted) {
|
||||||
Log("EsFS: Volume not unmounted, exiting...\n");
|
Log("EsFS: Volume not unmounted, exiting...\n");
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
superblock.mounted = 1;
|
superblock.mounted = 1;
|
||||||
WriteBlock(1, 1, &superblock);
|
|
||||||
|
if (!WriteBlock(1, 1, &superblock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
blockSize = superblock.blockSize;
|
blockSize = superblock.blockSize;
|
||||||
|
|
||||||
// Read the group descriptor table.
|
// Read the group descriptor table.
|
||||||
groupDescriptorTable = (GroupDescriptor *) malloc(superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1);
|
groupDescriptorTable = (GroupDescriptor *) malloc(superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1);
|
||||||
ReadBlock(superblock.gdtFirstBlock, (superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1) / superblock.blockSize, groupDescriptorTable);
|
|
||||||
|
if (!ReadBlock(superblock.gdtFirstBlock, (superblock.groupCount * sizeof(GroupDescriptor) + superblock.blockSize - 1) / superblock.blockSize, groupDescriptorTable)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmountVolume() {
|
void UnmountVolume() {
|
||||||
|
@ -939,11 +998,14 @@ void UnmountVolume() {
|
||||||
|
|
||||||
bool FindNode(const char *cName, DirectoryEntry *node, DirectoryEntryReference directoryReference) {
|
bool FindNode(const char *cName, DirectoryEntry *node, DirectoryEntryReference directoryReference) {
|
||||||
DirectoryEntry directory;
|
DirectoryEntry directory;
|
||||||
ReadDirectoryEntryReference(directoryReference, &directory);
|
if (!ReadDirectoryEntryReference(directoryReference, &directory)) return false;
|
||||||
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < directoryAttribute->childNodes; i++) {
|
for (uintptr_t i = 0; i < directoryAttribute->childNodes; i++) {
|
||||||
AccessNode(&directory, node, sizeof(DirectoryEntry) * i, sizeof(DirectoryEntry), NULL, true);
|
if (!AccessNode(&directory, node, sizeof(DirectoryEntry) * i, sizeof(DirectoryEntry), NULL, true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AttributeFilename *filename = (AttributeFilename *) FindAttribute(node, ESFS_ATTRIBUTE_FILENAME);
|
AttributeFilename *filename = (AttributeFilename *) FindAttribute(node, ESFS_ATTRIBUTE_FILENAME);
|
||||||
|
|
||||||
if (filename->length == strlen(cName) && 0 == memcmp(filename->filename, cName, filename->length)) {
|
if (filename->length == strlen(cName) && 0 == memcmp(filename->filename, cName, filename->length)) {
|
||||||
|
@ -973,7 +1035,7 @@ typedef struct ImportNode {
|
||||||
bool isFile;
|
bool isFile;
|
||||||
} ImportNode;
|
} ImportNode;
|
||||||
|
|
||||||
uint64_t Import(ImportNode node, DirectoryEntryReference parentDirectory) {
|
int64_t Import(ImportNode node, DirectoryEntryReference parentDirectory) {
|
||||||
uint64_t totalSize = 0;
|
uint64_t totalSize = 0;
|
||||||
|
|
||||||
for (uintptr_t i = 0; i < arrlenu(node.children); i++) {
|
for (uintptr_t i = 0; i < arrlenu(node.children); i++) {
|
||||||
|
@ -989,24 +1051,36 @@ uint64_t Import(ImportNode node, DirectoryEntryReference parentDirectory) {
|
||||||
DirectoryEntryReference reference;
|
DirectoryEntryReference reference;
|
||||||
DirectoryEntry entry;
|
DirectoryEntry entry;
|
||||||
|
|
||||||
AddNode(node.children[i].name, ESFS_NODE_TYPE_FILE, &entry, &reference, parentDirectory);
|
if (!AddNode(node.children[i].name, ESFS_NODE_TYPE_FILE, &entry, &reference, parentDirectory)) {
|
||||||
ResizeNode(&entry, fileLength);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ResizeNode(&entry, fileLength)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
totalSize += fileLength;
|
totalSize += fileLength;
|
||||||
|
|
||||||
AccessNode(&entry, data, 0, fileLength, NULL, false);
|
if (!AccessNode(&entry, data, 0, fileLength, NULL, false)) {
|
||||||
WriteDirectoryEntryReference(reference, &entry);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteDirectoryEntryReference(reference, &entry)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DirectoryEntryReference reference;
|
DirectoryEntryReference reference;
|
||||||
AddNode(node.children[i].name, ESFS_NODE_TYPE_DIRECTORY, NULL, &reference, parentDirectory);
|
if (!AddNode(node.children[i].name, ESFS_NODE_TYPE_DIRECTORY, NULL, &reference, parentDirectory)) return -1;
|
||||||
uint64_t size = Import(node.children[i], reference);
|
int64_t size = Import(node.children[i], reference);
|
||||||
|
if (size == -1) return -1;
|
||||||
DirectoryEntry directory;
|
DirectoryEntry directory;
|
||||||
ReadDirectoryEntryReference(reference, &directory);
|
if (!ReadDirectoryEntryReference(reference, &directory)) return -1;
|
||||||
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
AttributeDirectory *directoryAttribute = (AttributeDirectory *) FindAttribute(&directory, ESFS_ATTRIBUTE_DIRECTORY);
|
||||||
directoryAttribute->totalSize = size;
|
directoryAttribute->totalSize = size;
|
||||||
WriteDirectoryEntryReference(reference, &directory);
|
if (!WriteDirectoryEntryReference(reference, &directory)) return -1;
|
||||||
totalSize += size;
|
totalSize += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,18 +1089,18 @@ uint64_t Import(ImportNode node, DirectoryEntryReference parentDirectory) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osInstallation,
|
bool Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osInstallation,
|
||||||
void *kernel, size_t kernelBytes) {
|
void *kernel, size_t kernelBytes) {
|
||||||
assert(sizeof(Superblock) == 8192);
|
assert(sizeof(Superblock) == 8192);
|
||||||
|
|
||||||
if (driveSize < ESFS_DRIVE_MINIMUM_SIZE) {
|
if (driveSize < ESFS_DRIVE_MINIMUM_SIZE) {
|
||||||
Log("Error: Cannot create a drive of %d bytes (too small).\n", (int) driveSize);
|
Log("Error: Cannot create a drive of %d bytes (too small).\n", (int) driveSize);
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(volumeName) > ESFS_MAXIMUM_VOLUME_NAME_LENGTH) {
|
if (strlen(volumeName) > ESFS_MAXIMUM_VOLUME_NAME_LENGTH) {
|
||||||
Log("Error: Volume name '%s' is too long; must be <= %d bytes.\n", volumeName, (int) ESFS_MAXIMUM_VOLUME_NAME_LENGTH);
|
Log("Error: Volume name '%s' is too long; must be <= %d bytes.\n", volumeName, (int) ESFS_MAXIMUM_VOLUME_NAME_LENGTH);
|
||||||
exit(1);
|
EsFSError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the volume.
|
// Format the volume.
|
||||||
|
@ -1092,9 +1166,15 @@ void Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osIns
|
||||||
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
entry->checksum = CalculateCRC32(entry, sizeof(DirectoryEntry), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteBytes(blockCoreNodes * superblock.blockSize, sizeof(coreNodes), &coreNodes);
|
if (!WriteBytes(blockCoreNodes * superblock.blockSize, sizeof(coreNodes), &coreNodes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
superblock.checksum = CalculateCRC32(&superblock, sizeof(Superblock), 0);
|
superblock.checksum = CalculateCRC32(&superblock, sizeof(Superblock), 0);
|
||||||
WriteBytes(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE, &superblock);
|
|
||||||
|
if (!WriteBytes(ESFS_BOOT_SUPER_BLOCK_SIZE, ESFS_BOOT_SUPER_BLOCK_SIZE, &superblock)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
GroupDescriptor *buffer = (GroupDescriptor *) malloc(superblock.groupCount * sizeof(GroupDescriptor));
|
GroupDescriptor *buffer = (GroupDescriptor *) malloc(superblock.groupCount * sizeof(GroupDescriptor));
|
||||||
|
@ -1112,34 +1192,52 @@ void Format(uint64_t driveSize, const char *volumeName, EsUniqueIdentifier osIns
|
||||||
buffer[i].blockBitmap = blockGroup0Bitmap;
|
buffer[i].blockBitmap = blockGroup0Bitmap;
|
||||||
buffer[i].bitmapChecksum = CalculateCRC32(firstGroupBitmap, sizeof(firstGroupBitmap), 0);
|
buffer[i].bitmapChecksum = CalculateCRC32(firstGroupBitmap, sizeof(firstGroupBitmap), 0);
|
||||||
buffer[i].largestExtent = superblock.blocksPerGroup - superblock.blocksUsed;
|
buffer[i].largestExtent = superblock.blocksPerGroup - superblock.blocksUsed;
|
||||||
WriteBytes(blockGroup0Bitmap * superblock.blockSize, sizeof(firstGroupBitmap), &firstGroupBitmap);
|
|
||||||
|
if (!WriteBytes(blockGroup0Bitmap * superblock.blockSize, sizeof(firstGroupBitmap), &firstGroupBitmap)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[i].checksum = CalculateCRC32(buffer + i, sizeof(GroupDescriptor), 0);
|
buffer[i].checksum = CalculateCRC32(buffer + i, sizeof(GroupDescriptor), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteBytes(superblock.gdtFirstBlock * superblock.blockSize, superblock.groupCount * sizeof(GroupDescriptor), buffer);
|
if (!WriteBytes(superblock.gdtFirstBlock * superblock.blockSize, superblock.groupCount * sizeof(GroupDescriptor), buffer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the kernel.
|
// Add the kernel.
|
||||||
|
|
||||||
{
|
if (MountVolume()) {
|
||||||
MountVolume();
|
|
||||||
|
|
||||||
DirectoryEntryReference reference = superblock.kernel;
|
DirectoryEntryReference reference = superblock.kernel;
|
||||||
DirectoryEntry entry;
|
DirectoryEntry entry;
|
||||||
EsUniqueIdentifier unused = {};
|
EsUniqueIdentifier unused = {};
|
||||||
|
|
||||||
NewDirectoryEntry(&entry, ESFS_NODE_TYPE_FILE, unused, "Kernel");
|
NewDirectoryEntry(&entry, ESFS_NODE_TYPE_FILE, unused, "Kernel");
|
||||||
WriteDirectoryEntryReference(reference, &entry);
|
|
||||||
ResizeNode(&entry, kernelBytes);
|
if (WriteDirectoryEntryReference(reference, &entry)) {
|
||||||
AccessNode(&entry, kernel, 0, kernelBytes, NULL, false);
|
if (ResizeNode(&entry, kernelBytes)) {
|
||||||
WriteDirectoryEntryReference(reference, &entry);
|
if (AccessNode(&entry, kernel, 0, kernelBytes, NULL, false)) {
|
||||||
|
WriteDirectoryEntryReference(reference, &entry);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
UnmountVolume();
|
UnmountVolume();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -321,6 +321,10 @@ DEFINE_INTERFACE_STRING(InstallerCompleteFromOther, "Installation has completed
|
||||||
DEFINE_INTERFACE_STRING(InstallerCompleteFromUSB, "Installation has completed successfully. Disconnect the installation USB, 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");
|
DEFINE_INTERFACE_STRING(InstallerVolumeLabel, "Essence HD");
|
||||||
DEFINE_INTERFACE_STRING(InstallerUseMBR, "Use legacy BIOS boot (select for older computers)");
|
DEFINE_INTERFACE_STRING(InstallerUseMBR, "Use legacy BIOS boot (select for older computers)");
|
||||||
|
DEFINE_INTERFACE_STRING(InstallerFailedArchiveCRCError, "The installation data has been corrupted. Create a new installation USB or disk, and try again.");
|
||||||
|
DEFINE_INTERFACE_STRING(InstallerFailedGeneric, "The installation could not complete. This likely means that the drive you selected is failing. Try installing on a different drive.");
|
||||||
|
DEFINE_INTERFACE_STRING(InstallerFailedResources, "The installation could not complete. Your computer does not have enough memory to install " SYSTEM_BRAND_SHORT);
|
||||||
|
DEFINE_INTERFACE_STRING(InstallerNotSupported, "Your computer does not meet the minimum system requirements to install " SYSTEM_BRAND_SHORT ". Remove the installer, and restart your computer.");
|
||||||
|
|
||||||
// TODO System Monitor.
|
// TODO System Monitor.
|
||||||
|
|
||||||
|
|
|
@ -1108,7 +1108,6 @@ void DoCommand(const char *l) {
|
||||||
FILE *f = fopen("bin/temp.dat", "wb");
|
FILE *f = fopen("bin/temp.dat", "wb");
|
||||||
uint64_t crc64 = 0, uncompressed = 0;
|
uint64_t crc64 = 0, uncompressed = 0;
|
||||||
GatherFilesForInstallerArchive(f, "root", "", &crc64, &uncompressed);
|
GatherFilesForInstallerArchive(f, "root", "", &crc64, &uncompressed);
|
||||||
fwrite(&crc64, 1, sizeof(crc64), f);
|
|
||||||
uint32_t sizeMB = ftell(f) / 1000000;
|
uint32_t sizeMB = ftell(f) / 1000000;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
printf("Compressing %d MB...\n", sizeMB);
|
printf("Compressing %d MB...\n", sizeMB);
|
||||||
|
@ -1117,8 +1116,9 @@ void DoCommand(const char *l) {
|
||||||
lstat("bin/installer_archive.dat", &s);
|
lstat("bin/installer_archive.dat", &s);
|
||||||
printf("Compressed to %d MB.\n", (uint32_t) (s.st_size / 1000000));
|
printf("Compressed to %d MB.\n", (uint32_t) (s.st_size / 1000000));
|
||||||
unlink("bin/temp.dat");
|
unlink("bin/temp.dat");
|
||||||
f = fopen("bin/installer_metadata.dat", "ab");
|
f = fopen("bin/installer_metadata.dat", "wb");
|
||||||
fwrite(&uncompressed, 1, sizeof(uncompressed), f);
|
fwrite(&uncompressed, 1, sizeof(uncompressed), f);
|
||||||
|
fwrite(&crc64, 1, sizeof(crc64), f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
} else if (0 == strcmp(l, "config")) {
|
} else if (0 == strcmp(l, "config")) {
|
||||||
BuildUtilities();
|
BuildUtilities();
|
||||||
|
|
|
@ -129,6 +129,8 @@ File FileOpen(const char *path, char mode) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define EsFSError() exit(1)
|
||||||
|
|
||||||
#include "../shared/hash.cpp"
|
#include "../shared/hash.cpp"
|
||||||
#include "../shared/partitions.cpp"
|
#include "../shared/partitions.cpp"
|
||||||
#include "build_common.h"
|
#include "build_common.h"
|
||||||
|
@ -1058,7 +1060,7 @@ void BuildBootloader(Application *application) {
|
||||||
File _drive;
|
File _drive;
|
||||||
uint64_t _partitionOffset;
|
uint64_t _partitionOffset;
|
||||||
|
|
||||||
void ReadBlock(uint64_t block, uint64_t count, void *buffer) {
|
bool ReadBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
FileSeek(_drive, block * blockSize + _partitionOffset);
|
FileSeek(_drive, block * blockSize + _partitionOffset);
|
||||||
// printf("read of block %ld\n", block);
|
// printf("read of block %ld\n", block);
|
||||||
|
|
||||||
|
@ -1066,9 +1068,11 @@ void ReadBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
Log("Error: Could not read blocks %d->%d of drive.\n", (int) block, (int) (block + count));
|
Log("Error: Could not read blocks %d->%d of drive.\n", (int) block, (int) (block + count));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBlock(uint64_t block, uint64_t count, void *buffer) {
|
bool WriteBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
FileSeek(_drive, block * blockSize + _partitionOffset);
|
FileSeek(_drive, block * blockSize + _partitionOffset);
|
||||||
assert(block < 4294967296);
|
assert(block < 4294967296);
|
||||||
|
|
||||||
|
@ -1076,15 +1080,19 @@ void WriteBlock(uint64_t block, uint64_t count, void *buffer) {
|
||||||
Log("Error: Could not write to blocks %d->%d of drive.\n", (int) block, (int) (block + count));
|
Log("Error: Could not write to blocks %d->%d of drive.\n", (int) block, (int) (block + count));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBytes(uint64_t offset, uint64_t count, void *buffer) {
|
bool WriteBytes(uint64_t offset, uint64_t count, void *buffer) {
|
||||||
FileSeek(_drive, offset + _partitionOffset);
|
FileSeek(_drive, offset + _partitionOffset);
|
||||||
|
|
||||||
if (FileWrite(_drive, count, buffer) != count) {
|
if (FileWrite(_drive, count, buffer) != count) {
|
||||||
Log("Error: Could not write to bytes %d->%d of drive.\n", (int) offset, (int) (offset + count));
|
Log("Error: Could not write to bytes %d->%d of drive.\n", (int) offset, (int) (offset + count));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Install(const char *driveFile, uint64_t partitionSize, const char *partitionLabel) {
|
void Install(const char *driveFile, uint64_t partitionSize, const char *partitionLabel) {
|
||||||
|
|
Loading…
Reference in New Issue