mirror of https://gitlab.com/nakst/essence
installation to MBR
This commit is contained in:
parent
dfd80c3dcd
commit
f82e5d9a30
|
@ -1,3 +1,5 @@
|
|||
// TODO Report errors.
|
||||
// TODO GPT support.
|
||||
// TODO Handle crashing?
|
||||
// TODO Write any modified settings during installation.
|
||||
|
||||
|
@ -84,6 +86,9 @@ bool onWaitScreen, startedInstallation;
|
|||
EsBlockDeviceInformation blockDeviceInformation;
|
||||
EsHandle driveHandle;
|
||||
EsFileOffset partitionOffset;
|
||||
EsUniqueIdentifier installationIdentifier;
|
||||
EsMountPoint newFileSystemMountPoint;
|
||||
EsHandle mountNewFileSystemEvent;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
|
||||
|
@ -479,8 +484,6 @@ EsError Install() {
|
|||
m.user.context1.u = 6;
|
||||
EsMessagePost(nullptr, &m);
|
||||
|
||||
EsUniqueIdentifier installationIdentifier;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
installationIdentifier.d[i] = EsRandomU8();
|
||||
}
|
||||
|
@ -488,22 +491,31 @@ EsError Install() {
|
|||
Format(partitionBytes, interfaceString_InstallerVolumeLabel, installationIdentifier, kernel, kernelBytes);
|
||||
FlushWriteBuffer();
|
||||
|
||||
m.user.context1.u = 10;
|
||||
m.user.context1.u = 8;
|
||||
EsMessagePost(nullptr, &m);
|
||||
|
||||
// TODO Mount the new partition.
|
||||
// Mount the new partition and extract the archive to it.
|
||||
|
||||
// Extract the archive.
|
||||
// TODO Extract to the new partition.
|
||||
EsDeviceControl(drive.handle, ES_DEVICE_CONTROL_BLOCK_DETECT_FS, nullptr, nullptr);
|
||||
|
||||
error = Extract(EsLiteral("0:/installer_archive.dat"), EsLiteral("0:/test"));
|
||||
m.user.context1.u = 9;
|
||||
EsMessagePost(nullptr, &m);
|
||||
|
||||
if (ES_ERROR_TIMEOUT_REACHED == (EsError) EsWait(&mountNewFileSystemEvent, 1, 10000)) {
|
||||
return ES_ERROR_TIMEOUT_REACHED;
|
||||
}
|
||||
|
||||
error = Extract(EsLiteral("0:/installer_archive.dat"), newFileSystemMountPoint.prefix, newFileSystemMountPoint.prefixBytes);
|
||||
if (error != ES_SUCCESS) return error;
|
||||
|
||||
return ES_SUCCESS;
|
||||
}
|
||||
|
||||
void InstallThread(EsGeneric) {
|
||||
Install();
|
||||
EsPerformanceTimerPush();
|
||||
EsError error = Install();
|
||||
EsAssert(error == ES_SUCCESS); // TODO Reporting errors.
|
||||
EsPrint("Installation finished in %Fs. Extracted %D from the archive.\n", EsPerformanceTimerPop(), metadata->totalUncompressedBytes);
|
||||
|
||||
EsMessage m = { MSG_SET_PROGRESS };
|
||||
m.user.context1.u = 100;
|
||||
|
@ -592,6 +604,8 @@ void _start() {
|
|||
metadata = (InstallerMetadata *) EsFileReadAll(EsLiteral("0:/installer_metadata.dat"), nullptr);
|
||||
EsAssert(metadata);
|
||||
|
||||
mountNewFileSystemEvent = EsEventCreate(true);
|
||||
|
||||
EsWindow *window = EsWindowCreate(_EsInstanceCreate(sizeof(EsInstance), nullptr), ES_WINDOW_PLAIN);
|
||||
EsHandle handle = _EsWindowGetHandle(window);
|
||||
window->instance->window = window;
|
||||
|
@ -718,6 +732,24 @@ void _start() {
|
|||
if (!startedInstallation) {
|
||||
ConnectedDriveRemove(message->device);
|
||||
}
|
||||
} else if (message->type == ES_MSG_REGISTER_FILE_SYSTEM) {
|
||||
EsVolumeInformation information;
|
||||
|
||||
if (EsMountPointGetVolumeInformation(message->registerFileSystem.mountPoint->prefix, message->registerFileSystem.mountPoint->prefixBytes, &information)) {
|
||||
bool isBootable = false;
|
||||
|
||||
for (uintptr_t i = 0; i < sizeof(EsUniqueIdentifier); i++) {
|
||||
if (information.installationIdentifier.d[i]) {
|
||||
isBootable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBootable && 0 == EsMemoryCompare(&information.installationIdentifier, &installationIdentifier, sizeof(EsUniqueIdentifier))) {
|
||||
newFileSystemMountPoint = *message->registerFileSystem.mountPoint;
|
||||
EsEventSet(mountNewFileSystemEvent);
|
||||
}
|
||||
}
|
||||
} else if (message->type == MSG_SET_PROGRESS) {
|
||||
if (progress != message->user.context1.u) {
|
||||
char buffer[128];
|
||||
|
|
|
@ -1134,6 +1134,7 @@ enum EsDeviceControlType {
|
|||
ES_DEVICE_CONTROL_BLOCK_GET_INFORMATION = 0x1001
|
||||
ES_DEVICE_CONTROL_BLOCK_READ = 0x1002
|
||||
ES_DEVICE_CONTROL_BLOCK_WRITE = 0x1003
|
||||
ES_DEVICE_CONTROL_BLOCK_DETECT_FS = 0x1004 // Detect file systems. All existing file systems must have been unmounted.
|
||||
}
|
||||
|
||||
function_pointer int EsUICallback(struct EsElement *element, struct EsMessage *message);
|
||||
|
@ -1508,6 +1509,7 @@ struct EsVolumeInformation {
|
|||
EsObjectID id;
|
||||
EsFileOffset spaceTotal;
|
||||
EsFileOffset spaceUsed;
|
||||
EsUniqueIdentifier installationIdentifier; // Currently only supported by EsFS.
|
||||
};
|
||||
|
||||
// User interface messages.
|
||||
|
|
|
@ -68,6 +68,7 @@ EsError FSFileControl(KNode *node, uint32_t flags);
|
|||
bool FSTrimCachedNode(MMObjectCache *);
|
||||
bool FSTrimCachedDirectoryEntry(MMObjectCache *);
|
||||
EsError FSBlockDeviceAccess(KBlockDeviceAccessRequest request);
|
||||
void FSDetectFileSystem(KBlockDevice *device);
|
||||
|
||||
struct {
|
||||
KWriterLock fileSystemsLock;
|
||||
|
@ -1771,6 +1772,14 @@ bool FSFileSystemInitialise(KFileSystem *fileSystem) {
|
|||
}
|
||||
|
||||
void FSDetectFileSystem(KBlockDevice *device) {
|
||||
KMutexAcquire(&device->detectFileSystemMutex);
|
||||
EsDefer(KMutexRelease(&device->detectFileSystemMutex));
|
||||
|
||||
if (device->children.Length()) {
|
||||
// The file system or partitions on the device have already been detected and mounted.
|
||||
return;
|
||||
}
|
||||
|
||||
KernelLog(LOG_INFO, "FS", "detect file system", "Detecting file system on block device '%s'.\n", device->information.modelBytes, device->information.model);
|
||||
|
||||
if (device->information.nestLevel > 4) {
|
||||
|
@ -1786,31 +1795,30 @@ void FSDetectFileSystem(KBlockDevice *device) {
|
|||
|
||||
uint8_t *signatureBlock = (uint8_t *) EsHeapAllocate(sectorsToRead * device->information.sectorSize, false, K_FIXED);
|
||||
|
||||
if (!signatureBlock) {
|
||||
return;
|
||||
}
|
||||
if (signatureBlock) {
|
||||
device->signatureBlock = signatureBlock;
|
||||
|
||||
device->signatureBlock = signatureBlock;
|
||||
KDMABuffer dmaBuffer = { (uintptr_t) signatureBlock };
|
||||
KBlockDeviceAccessRequest request = {};
|
||||
request.device = device;
|
||||
request.count = sectorsToRead * device->information.sectorSize;
|
||||
request.operation = K_ACCESS_READ;
|
||||
request.buffer = &dmaBuffer;
|
||||
|
||||
KDMABuffer dmaBuffer = { (uintptr_t) signatureBlock };
|
||||
KBlockDeviceAccessRequest request = {};
|
||||
request.device = device;
|
||||
request.count = sectorsToRead * device->information.sectorSize;
|
||||
request.operation = K_ACCESS_READ;
|
||||
request.buffer = &dmaBuffer;
|
||||
|
||||
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 {
|
||||
if (!device->information.noMBR && FSCheckMBR(device)) {
|
||||
// Found an MBR.
|
||||
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 {
|
||||
KDeviceAttach(device, "Files", FSSignatureCheck);
|
||||
if (!device->information.noMBR && FSCheckMBR(device)) {
|
||||
// Found an MBR.
|
||||
} else {
|
||||
KDeviceAttach(device, "Files", FSSignatureCheck);
|
||||
}
|
||||
}
|
||||
|
||||
EsHeapFree(signatureBlock, sectorsToRead * device->information.sectorSize, K_FIXED);
|
||||
}
|
||||
|
||||
EsHeapFree(signatureBlock, sectorsToRead * device->information.sectorSize, K_FIXED);
|
||||
KDeviceCloseHandle(device);
|
||||
}
|
||||
|
||||
|
@ -1819,6 +1827,8 @@ void FSDetectFileSystem(KBlockDevice *device) {
|
|||
//////////////////////////////////////////
|
||||
|
||||
void FSRegisterBootFileSystem(KFileSystem *fileSystem, EsUniqueIdentifier identifier) {
|
||||
fileSystem->installationIdentifier = identifier;
|
||||
|
||||
if (!EsMemoryCompare(&identifier, &installationID, sizeof(EsUniqueIdentifier))) {
|
||||
KWriterLockTake(&fs.fileSystemsLock, K_LOCK_EXCLUSIVE);
|
||||
|
||||
|
|
|
@ -2110,6 +2110,19 @@ MMSpace *MMGetCurrentProcessSpace() {
|
|||
return GetCurrentThread()->process->vmm;
|
||||
}
|
||||
|
||||
bool MMFaultRange(uintptr_t address, uintptr_t byteCount) {
|
||||
uintptr_t start = address & ~(K_PAGE_SIZE - 1);
|
||||
uintptr_t end = (address + byteCount - 1) & ~(K_PAGE_SIZE - 1);
|
||||
|
||||
for (uintptr_t page = start; page <= end; page += K_PAGE_SIZE) {
|
||||
if (!MMArchHandlePageFault(page, ES_FLAGS_DEFAULT)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MMArchRemap(MMSpace *space, const void *virtualAddress, uintptr_t newPhysicalAddress) {
|
||||
if (ProcessorAreInterruptsEnabled()) {
|
||||
KernelPanic("MMArchRemap - Cannot remap address with interrupts enabled (does not invalidate the page on other processors).\n");
|
||||
|
|
|
@ -635,6 +635,7 @@ struct KBlockDevice : KDevice {
|
|||
K_PRIVATE
|
||||
|
||||
uint8_t *signatureBlock; // Signature block. Only valid during fileSystem detection.
|
||||
KMutex detectFileSystemMutex;
|
||||
};
|
||||
|
||||
#define FS_PARTITION_DEVICE_NO_MBR (1 << 0)
|
||||
|
@ -881,6 +882,7 @@ struct KFileSystem : KDevice {
|
|||
|
||||
KMutex moveMutex;
|
||||
bool isBootFileSystem, unmounting;
|
||||
EsUniqueIdentifier installationIdentifier;
|
||||
volatile uint64_t totalHandleCount;
|
||||
CCSpace cacheSpace;
|
||||
|
||||
|
|
|
@ -213,16 +213,8 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_COMMIT) {
|
|||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_MEMORY_FAULT_RANGE) {
|
||||
uintptr_t start = argument0 & ~(K_PAGE_SIZE - 1);
|
||||
uintptr_t end = (argument0 + argument1 - 1) & ~(K_PAGE_SIZE - 1);
|
||||
|
||||
for (uintptr_t page = start; page <= end; page += K_PAGE_SIZE) {
|
||||
if (!MMArchHandlePageFault(page, ES_FLAGS_DEFAULT)) {
|
||||
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||
bool success = MMFaultRange(argument0, argument1);
|
||||
SYSCALL_RETURN(success ? ES_SUCCESS : ES_FATAL_ERROR_INVALID_BUFFER, !success);
|
||||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_PROCESS_CREATE) {
|
||||
|
@ -758,6 +750,7 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_VOLUME_GET_INFORMATION) {
|
|||
information.spaceTotal = fileSystem->spaceTotal;
|
||||
information.id = fileSystem->objectID;
|
||||
information.flags = fileSystem->write ? ES_FLAGS_DEFAULT : ES_VOLUME_READ_ONLY;
|
||||
information.installationIdentifier = fileSystem->installationIdentifier;
|
||||
|
||||
SYSCALL_WRITE(argument1, &information, sizeof(EsVolumeInformation));
|
||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||
|
@ -1837,6 +1830,13 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_DEVICE_CONTROL) {
|
|||
EsFileOffset parameters[2];
|
||||
SYSCALL_READ(parameters, dq, sizeof(EsFileOffset) * 2);
|
||||
SYSCALL_BUFFER(dp, parameters[1], 1, !write /* whether the buffer will be written to */);
|
||||
|
||||
// Since the request is not done via the cache, we need to fault the pages in.
|
||||
// TODO Formalize this notion in the memory manager with page locking.
|
||||
if (!MMFaultRange(dp, parameters[1])) {
|
||||
SYSCALL_RETURN(ES_FATAL_ERROR_INVALID_BUFFER, true);
|
||||
}
|
||||
|
||||
KBlockDeviceAccessRequest request = {};
|
||||
request.device = block;
|
||||
request.offset = parameters[0];
|
||||
|
@ -1845,6 +1845,9 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_DEVICE_CONTROL) {
|
|||
request.buffer = &dmaBuffer;
|
||||
request.flags = FS_BLOCK_ACCESS_SOFT_ERRORS;
|
||||
SYSCALL_RETURN(FSBlockDeviceAccess(request), false);
|
||||
} else if (type == ES_DEVICE_CONTROL_BLOCK_DETECT_FS) {
|
||||
KDeviceOpenHandle(block);
|
||||
FSDetectFileSystem(block); // Closes handle.
|
||||
} else {
|
||||
SYSCALL_RETURN(ES_FATAL_ERROR_UNKNOWN_SYSCALL, true);
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ 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(InstallerDriveAlreadyHasPartitions, "The drive already has data on it. 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");
|
||||
|
|
|
@ -447,7 +447,7 @@ void Run(int emulator, int log, int debug) {
|
|||
const char *secondaryDriveMB = GetOptionString("Emulator.SecondaryDriveMB");
|
||||
char secondaryDriveFlags[256];
|
||||
|
||||
if (secondaryDriveMB) {
|
||||
if (secondaryDriveMB && atoi(secondaryDriveMB)) {
|
||||
CallSystemF("dd if=/dev/zero of=bin/drive2 bs=1048576 count=%d", atoi(secondaryDriveMB));
|
||||
snprintf(secondaryDriveFlags, sizeof(secondaryDriveFlags),
|
||||
"-drive file=bin/drive2,if=none,id=mydisk2,format=raw "
|
||||
|
|
Loading…
Reference in New Issue