From 475bd7c26e017f07dd6b4ee436abc4e83bb29c21 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 4 Nov 2015 14:06:17 +0100 Subject: [PATCH] Add support for multiple initrds. --- kernel/Makefile | 1 - kernel/crc32.cpp | 72 ------ kernel/include/sortix/kernel/crc32.h | 46 ---- kernel/initrd.cpp | 327 ++++++++++++--------------- kernel/initrd.h | 12 +- kernel/kernel.cpp | 29 +-- 6 files changed, 160 insertions(+), 327 deletions(-) delete mode 100644 kernel/crc32.cpp delete mode 100644 kernel/include/sortix/kernel/crc32.h diff --git a/kernel/Makefile b/kernel/Makefile index e3eec6ac..13a74d38 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -83,7 +83,6 @@ clock.o \ com.o \ copy.o \ $(CPUDIR)/kthread.o \ -crc32.o \ debugger.o \ descriptor.o \ disk/ahci/ahci.o \ diff --git a/kernel/crc32.cpp b/kernel/crc32.cpp deleted file mode 100644 index 7214dc19..00000000 --- a/kernel/crc32.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - - Copyright(C) Jonas 'Sortie' Termansen 2012. - Copyright(C) Krzysztof Dabrowski 1999, 2000. - Copyright(C) ElysiuM deeZine 1999, 2000. - Based on implementation by Finn Yannick Jacobs. - - This file is part of Sortix. - - Sortix is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation, either version 3 of the License, or (at your option) any later - version. - - Sortix is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - You should have received a copy of the GNU General Public License along with - Sortix. If not, see . - - crc32.cpp - Calculates a CRC32 Checksum of binary data. - -*******************************************************************************/ - -#include -#include - -namespace Sortix { -namespace CRC32 { - -void GenerateTable(uint32_t tabel[256]) -{ - uint32_t poly = 0xEDB88320U; - for ( uint32_t i = 0; i < 256; i++ ) - { - uint32_t crc = i; - for ( uint32_t j = 8; 0 < j; j-- ) - { - if ( crc & 1 ) { crc = (crc >> 1) ^ poly; } - else { crc >>= 1; } - } - tabel[i] = crc; - } -} - -uint32_t Continue(uint32_t tabel[256], uint32_t crc, uint8_t* block, - size_t size) -{ - for ( size_t i = 0; i < size; i++ ) - { - crc = ((crc >> 8) & 0x00FFFFFF) ^ tabel[(crc ^ *block++) & 0xFF]; - } - return crc; -} - -uint32_t Finish(uint32_t crc) -{ - return crc ^ 0xFFFFFFFF; -} - -uint32_t Hash(uint8_t* block, size_t size) -{ - uint32_t tabel[256]; - GenerateTable(tabel); - return Finish(Continue(tabel, START_SEED, block, size)); -} - -} // namespace CRC32 -} // namespace Sortix diff --git a/kernel/include/sortix/kernel/crc32.h b/kernel/include/sortix/kernel/crc32.h deleted file mode 100644 index f4a6f0a5..00000000 --- a/kernel/include/sortix/kernel/crc32.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - - Copyright(C) Jonas 'Sortie' Termansen 2012. - Copyright(C) Krzysztof Dabrowski 1999, 2000. - Copyright(C) ElysiuM deeZine 1999, 2000. - Based on implementation by Finn Yannick Jacobs. - - This file is part of Sortix. - - Sortix is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation, either version 3 of the License, or (at your option) any later - version. - - Sortix is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - You should have received a copy of the GNU General Public License along with - Sortix. If not, see . - - sortix/kernel/crc32.h - Calculates a CRC32 Checksum of binary data. - -*******************************************************************************/ - -#ifndef SORTIX_CRC32_H -#define SORTIX_CRC32_H - -#include -#include - -namespace Sortix { -namespace CRC32 { - -const uint32_t START_SEED = 0xFFFFFFFF; -void GenerateTable(uint32_t tabel[256]); -uint32_t Continue(uint32_t tabel[256], uint32_t crc, uint8_t* buf, size_t size); -uint32_t Finish(uint32_t crc); -uint32_t Hash(uint8_t* block, size_t size); - -} // namespace CRC32 -} // namespace Sortix - -#endif diff --git a/kernel/initrd.cpp b/kernel/initrd.cpp index d32de797..b99b7b83 100644 --- a/kernel/initrd.cpp +++ b/kernel/initrd.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. This file is part of Sortix. @@ -18,7 +18,7 @@ Sortix. If not, see . initrd.cpp - Extracts the initrd into the initial memory filesystem. + Extracts initrds into the initial memory filesystem. *******************************************************************************/ @@ -39,7 +39,6 @@ #include #include -#include #include #include #include @@ -50,9 +49,9 @@ #include #include "initrd.h" +#include "multiboot.h" namespace Sortix { -namespace InitRD { // TODO: The initrd is not being properly verified. // TODO: The initrd is not handled in an endian-neutral manner. @@ -61,44 +60,27 @@ struct initrd_context { uint8_t* initrd; size_t initrd_size; - size_t amount_extracted; - initrd_superblock_t* sb; + addr_t initrd_unmap_start; + addr_t initrd_unmap_end; + struct initrd_superblock* sb; Ref links; ioctx_t ioctx; - int last_percent; }; -void initrd_activity(const char* status, const char* format, ...) +// TODO: GRUB is currently buggy and doesn't ensure that other things are placed +// at the end of a module, i.e. that the module doesn't own all the bugs +// that it spans. It's thus risky to actually recycle the last page if the +// module doesn't use all of it. Remove this compatibility when this has +// been fixed in GRUB and a few years have passed such that most GRUB +// systems have this fixed. +static void UnmapInitrdPage(struct initrd_context* ctx, addr_t vaddr) { - Log::PrintF("\r"); - Log::PrintF(" [%6.6s] ", status); - va_list ap; - va_start(ap, format); - Log::PrintFV(format, ap); - va_end(ap); - Log::PrintF("..."); - size_t column, row; - while ( Log::GetCursor(&column, &row), column != Log::Width() ) - Log::PrintF(" "); - Log::PrintF("\e[0J"); -} - -void initrd_activity_done() -{ - Log::PrintF("\r\e[0J"); -} - -void initrd_progress(struct initrd_context* ctx) -{ - int percent = 100; - if ( ctx->initrd_size && ctx->initrd_size != ctx->amount_extracted ) - percent = ((uint64_t) ctx->amount_extracted * 100) / ctx->initrd_size; - if ( percent == ctx->last_percent ) + if ( !Memory::LookUp(vaddr, NULL, NULL) ) return; - char status[6 + 1]; - snprintf(status, sizeof(status), " %3i%% ", percent); - initrd_activity(status, "Extracting ramdisk into initial filesystem"); - ctx->last_percent = percent; + addr_t addr = Memory::Unmap(vaddr); + if ( !(ctx->initrd_unmap_start <= addr && addr < ctx->initrd_unmap_end) ) + return; + Page::Put(addr, PAGE_USAGE_WASNT_ALLOCATED); } static mode_t initrd_mode_to_host_mode(uint32_t mode) @@ -115,20 +97,25 @@ static mode_t initrd_mode_to_host_mode(uint32_t mode) return result; } -static initrd_inode_t* initrd_get_inode(struct initrd_context* ctx, uint32_t inode) +static struct initrd_inode* initrd_get_inode(struct initrd_context* ctx, + uint32_t inode) { if ( ctx->sb->inodecount <= inode ) - return errno = EINVAL, (initrd_inode_t*) NULL; + return errno = EINVAL, (struct initrd_inode*) NULL; uint32_t pos = ctx->sb->inodeoffset + ctx->sb->inodesize * inode; - return (initrd_inode_t*) (ctx->initrd + pos); + return (struct initrd_inode*) (ctx->initrd + pos); } -static uint8_t* initrd_inode_get_data(struct initrd_context* ctx, initrd_inode_t* inode, size_t* size) +static uint8_t* initrd_inode_get_data(struct initrd_context* ctx, + struct initrd_inode* inode, + size_t* size) { return *size = inode->size, ctx->initrd + inode->dataoffset; } -static uint32_t initrd_directory_open(struct initrd_context* ctx, initrd_inode_t* inode, const char* name) +static uint32_t initrd_directory_open(struct initrd_context* ctx, + struct initrd_inode* inode, + const char* name) { if ( !INITRD_S_ISDIR(inode->mode) ) return errno = ENOTDIR, 0; @@ -136,7 +123,8 @@ static uint32_t initrd_directory_open(struct initrd_context* ctx, initrd_inode_t while ( offset < inode->size ) { uint32_t pos = inode->dataoffset + offset; - initrd_dirent* dirent = (initrd_dirent*) (ctx->initrd + pos); + struct initrd_dirent* dirent = + (struct initrd_dirent*) (ctx->initrd + pos); if ( dirent->namelen && !strcmp(dirent->name, name) ) return dirent->inode; offset += dirent->reclen; @@ -144,7 +132,9 @@ static uint32_t initrd_directory_open(struct initrd_context* ctx, initrd_inode_t return errno = ENOENT, 0; } -static const char* initrd_directory_get_filename(struct initrd_context* ctx, initrd_inode_t* inode, size_t index) +static const char* initrd_directory_get_filename(struct initrd_context* ctx, + struct initrd_inode* inode, + size_t index) { if ( !INITRD_S_ISDIR(inode->mode) ) return errno = ENOTDIR, (const char*) NULL; @@ -152,7 +142,8 @@ static const char* initrd_directory_get_filename(struct initrd_context* ctx, ini while ( offset < inode->size ) { uint32_t pos = inode->dataoffset + offset; - initrd_dirent* dirent = (initrd_dirent*) (ctx->initrd + pos); + struct initrd_dirent* dirent = + (struct initrd_dirent*) (ctx->initrd + pos); if ( index-- == 0 ) return dirent->name; offset += dirent->reclen; @@ -160,7 +151,8 @@ static const char* initrd_directory_get_filename(struct initrd_context* ctx, ini return errno = EINVAL, (const char*) NULL; } -static size_t initrd_directory_get_num_files(struct initrd_context* ctx, initrd_inode_t* inode) +static size_t initrd_directory_get_num_files(struct initrd_context* ctx, + struct initrd_inode* inode) { if ( !INITRD_S_ISDIR(inode->mode) ) return errno = ENOTDIR, 0; @@ -169,23 +161,26 @@ static size_t initrd_directory_get_num_files(struct initrd_context* ctx, initrd_ while ( offset < inode->size ) { uint32_t pos = inode->dataoffset + offset; - const initrd_dirent* dirent = (const initrd_dirent*) (ctx->initrd + pos); + const struct initrd_dirent* dirent = + (const struct initrd_dirent*) (ctx->initrd + pos); numentries++; offset += dirent->reclen; } return numentries; } -static bool ExtractNode(struct initrd_context* ctx, initrd_inode_t* inode, Ref node); +static void ExtractNode(struct initrd_context* ctx, + struct initrd_inode* inode, + Ref node); -static bool ExtractFile(struct initrd_context* ctx, initrd_inode_t* inode, Ref file) +static void ExtractFile(struct initrd_context* ctx, + struct initrd_inode* inode, + Ref file) { size_t filesize; uint8_t* data = initrd_inode_get_data(ctx, inode, &filesize); - if ( !data ) - return false; if ( file->truncate(&ctx->ioctx, filesize) != 0 ) - return false; + PanicF("initrd: truncate: %m"); size_t sofar = 0; while ( sofar < filesize ) { @@ -194,68 +189,71 @@ static bool ExtractFile(struct initrd_context* ctx, initrd_inode_t* inode, Refwrite(&ctx->ioctx, data + sofar, count); if ( numbytes <= 0 ) - return false; + PanicF("initrd: write: %m"); sofar += numbytes; - ctx->amount_extracted += numbytes; - initrd_progress(ctx); } - return true; } -static bool ExtractDir(struct initrd_context* ctx, initrd_inode_t* inode, Ref dir) +static void ExtractDir(struct initrd_context* ctx, + struct initrd_inode* inode, + Ref dir) { size_t numfiles = initrd_directory_get_num_files(ctx, inode); for ( size_t i = 0; i < numfiles; i++ ) { const char* name = initrd_directory_get_filename(ctx, inode, i); if ( !name ) - return false; + PanicF("initrd_directory_get_filename: %m"); if ( IsDotOrDotDot(name) ) continue; uint32_t childino = initrd_directory_open(ctx, inode, name); if ( !childino ) - return false; - initrd_inode_t* child = (initrd_inode_t*) initrd_get_inode(ctx, childino); + PanicF("initrd_directory_open: %s: %m", name); + struct initrd_inode* child = + (struct initrd_inode*) initrd_get_inode(ctx, childino); mode_t mode = initrd_mode_to_host_mode(child->mode); if ( INITRD_S_ISDIR(child->mode) ) { if ( dir->mkdir(&ctx->ioctx, name, mode) && errno != EEXIST ) - return false; - Ref desc = dir->open(&ctx->ioctx, name, O_SEARCH | O_DIRECTORY, 0); + PanicF("initrd: mkdir: %s: %m", name); + Ref desc = dir->open(&ctx->ioctx, name, + O_SEARCH | O_DIRECTORY, 0); if ( !desc ) - return false; - if ( !ExtractNode(ctx, child, desc) ) - return false; + PanicF("initrd: %s: %m", name); + ExtractNode(ctx, child, desc); } if ( INITRD_S_ISREG(child->mode) ) { assert(child->nlink != 0); char link_path[sizeof(childino) * 3]; snprintf(link_path, sizeof(link_path), "%ju", (uintmax_t) childino); - Ref existing(ctx->links->open(&ctx->ioctx, link_path, O_READ, 0)); + Ref existing(ctx->links->open(&ctx->ioctx, link_path, + O_READ, 0)); if ( !existing || dir->link(&ctx->ioctx, name, existing) != 0 ) { - Ref desc(dir->open(&ctx->ioctx, name, O_WRITE | O_CREATE, mode)); + Ref desc(dir->open(&ctx->ioctx, name, + O_WRITE | O_CREATE, mode)); if ( !desc ) - return false; - if ( !ExtractNode(ctx, child, desc) ) - return false; + PanicF("initrd: %s: %m", name); + ExtractNode(ctx, child, desc); if ( 2 <= child->nlink ) ctx->links->link(&ctx->ioctx, link_path, desc); } if ( --child->nlink == 0 && INITRD_S_ISREG(child->mode) ) { size_t filesize; - const uint8_t* data = initrd_inode_get_data(ctx, child, &filesize); + const uint8_t* data = + initrd_inode_get_data(ctx, child, &filesize); uintptr_t from = (uintptr_t) data; uintptr_t size = filesize; uintptr_t from_aligned = Page::AlignUp(from); uintptr_t from_distance = from_aligned - from; if ( from_distance <= size ) { - uintptr_t size_aligned = Page::AlignDown(size - from_distance); + uintptr_t size_aligned = + Page::AlignDown(size - from_distance); for ( size_t i = 0; i < size_aligned; i += Page::Size() ) - Page::Put(Memory::Unmap(from_aligned + i), PAGE_USAGE_WASNT_ALLOCATED); + UnmapInitrdPage(ctx, from_aligned + i); Memory::Flush(); } } @@ -264,122 +262,56 @@ static bool ExtractDir(struct initrd_context* ctx, initrd_inode_t* inode, Refsymlink(&ctx->ioctx, oldname, name); delete[] oldname; if ( ret < 0 ) - return false; - Ref desc = dir->open(&ctx->ioctx, name, O_READ | O_SYMLINK_NOFOLLOW, 0); + PanicF("initrd: symlink: %s", name); + Ref desc = dir->open(&ctx->ioctx, name, + O_READ | O_SYMLINK_NOFOLLOW, 0); if ( desc ) ExtractNode(ctx, child, desc); - ctx->amount_extracted += child->size; - initrd_progress(ctx); } } - - ctx->amount_extracted += inode->size; - initrd_progress(ctx); - return true; } -static bool ExtractNode(struct initrd_context* ctx, initrd_inode_t* inode, Ref node) +static void ExtractNode(struct initrd_context* ctx, + struct initrd_inode* inode, + Ref node) { if ( node->chmod(&ctx->ioctx, initrd_mode_to_host_mode(inode->mode)) < 0 ) - return false; + PanicF("initrd: chmod: %m"); if ( node->chown(&ctx->ioctx, inode->uid, inode->gid) < 0 ) - return false; + PanicF("initrd: chown: %m"); if ( INITRD_S_ISDIR(inode->mode) ) - if ( !ExtractDir(ctx, inode, node) ) - return false; + ExtractDir(ctx, inode, node); if ( INITRD_S_ISREG(inode->mode) ) - if ( !ExtractFile(ctx, inode, node) ) - return false; + ExtractFile(ctx, inode, node); struct timespec ctime = timespec_make((time_t) inode->ctime, 0); struct timespec mtime = timespec_make((time_t) inode->mtime, 0); if ( node->utimens(&ctx->ioctx, &mtime, &ctime, &mtime) < 0 ) - return false; - return true; + PanicF("initrd: utimens: %m"); } -bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc) +static void ExtractInitrd(Ref desc, struct initrd_context* ctx) { - initrd_activity(" ", "Verifying ramdisk checksum"); + ctx->sb = (struct initrd_superblock*) ctx->initrd; - // Allocate the needed kernel virtual address space. - addralloc_t initrd_addr_alloc; - if ( !AllocateKernelAddress(&initrd_addr_alloc, size) ) - PanicF("Can't allocate 0x%zx bytes of kernel address space for the " - "init ramdisk", size ); + if ( ctx->initrd_size < ctx->sb->fssize ) + Panic("Initrd header does not match its size"); - // Map the physical frames onto our address space. - addr_t mapat = initrd_addr_alloc.from; - for ( size_t i = 0; i < size; i += Page::Size() ) - if ( !Memory::Map(physaddr + i, mapat + i, PROT_KREAD | PROT_KWRITE) ) - PanicF("Unable to map the init ramdisk into virtual memory"); - Memory::Flush(); + if ( desc->mkdir(&ctx->ioctx, ".initrd-links", 0777) != 0 ) + PanicF("initrd: .initrd-links: %m"); - struct initrd_context ctx; - memset(&ctx, 0, sizeof(ctx)); - ctx.initrd = (uint8_t*) mapat; - ctx.initrd_size = size; - ctx.amount_extracted = 0; - ctx.last_percent = -1; - SetupKernelIOCtx(&ctx.ioctx); + if ( !(ctx->links = desc->open(&ctx->ioctx, ".initrd-links", + O_READ | O_DIRECTORY, 0)) ) + PanicF("initrd: .initrd-links: %m"); - if ( size < sizeof(*ctx.sb) ) - PanicF("initrd is too small"); - ctx.sb = (initrd_superblock_t*) ctx.initrd; - - if ( !String::StartsWith(ctx.sb->magic, "sortix-initrd") ) - PanicF("Invalid magic value in initrd. This means the ramdisk may have " - "been corrupted by the bootloader, or that an incompatible file " - "has been passed to the kernel."); - - if ( strcmp(ctx.sb->magic, "sortix-initrd-1") == 0 ) - PanicF("Sortix initrd format version 1 is no longer supported."); - - if ( strcmp(ctx.sb->magic, "sortix-initrd-2") != 0 ) - PanicF("The initrd has a format that isn't supported. Perhaps it is " - "too new? Try downgrade or regenerate the initrd."); - - if ( size < ctx.sb->fssize ) - PanicF("The initrd said it is %u bytes, but the kernel was only passed " - "%zu bytes by the bootloader, which is not enough.", - ctx.sb->fssize, size); - - uint32_t amount = ctx.sb->fssize - ctx.sb->sumsize; - uint8_t* filesum = ctx.initrd + amount; - if ( ctx.sb->sumalgorithm != INITRD_ALGO_CRC32 ) - { - Log::PrintF("Warning: InitRD checksum algorithm not supported\n"); - } - else - { - uint32_t crc32 = *((uint32_t*) filesum); - uint32_t filecrc32 = CRC32::Hash(ctx.initrd, amount); - if ( crc32 != filecrc32 ) - { - PanicF("InitRD had checksum %X, expected %X: this means the ramdisk " - "may have been corrupted by the bootloader.", filecrc32, crc32); - } - } - - initrd_activity(" OK ", "Verifying ramdisk checksum"); - - initrd_progress(&ctx); - - if ( desc->mkdir(&ctx.ioctx, ".initrd-links", 0777) != 0 ) - return false; - - if ( !(ctx.links = desc->open(&ctx.ioctx, ".initrd-links", O_READ | O_DIRECTORY, 0)) ) - return false; - - if ( !ExtractNode(&ctx, initrd_get_inode(&ctx, ctx.sb->root), desc) ) - return false; + ExtractNode(ctx, initrd_get_inode(ctx, ctx->sb->root), desc); union { @@ -387,38 +319,75 @@ bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc) uint8_t dirent_data[sizeof(struct dirent) + sizeof(uintmax_t) * 3]; }; - while ( 0 < ctx.links->readdirents(&ctx.ioctx, &dirent, sizeof(dirent_data)) && + while ( 0 < ctx->links->readdirents(&ctx->ioctx, &dirent, sizeof(dirent_data)) && ((const char*) dirent.d_name)[0] ) { if ( ((const char*) dirent.d_name)[0] == '.' ) continue; - ctx.links->unlinkat(&ctx.ioctx, dirent.d_name, AT_REMOVEFILE); - ctx.links->lseek(&ctx.ioctx, 0, SEEK_SET); + ctx->links->unlinkat(&ctx->ioctx, dirent.d_name, AT_REMOVEFILE); + ctx->links->lseek(&ctx->ioctx, 0, SEEK_SET); } - ctx.links.Reset(); + ctx->links.Reset(); - desc->unlinkat(&ctx.ioctx, ".initrd-links", AT_REMOVEDIR); + desc->unlinkat(&ctx->ioctx, ".initrd-links", AT_REMOVEDIR); +} - // Unmap the pages and return the physical frames for reallocation. - for ( size_t i = 0; i < initrd_addr_alloc.size; i += Page::Size() ) +static void ExtractModule(struct multiboot_mod_list* module, + Ref desc, + struct initrd_context* ctx) +{ + size_t mod_size = module->mod_end - module->mod_start; + + // Allocate the needed kernel virtual address space. + addralloc_t initrd_addr_alloc; + if ( !AllocateKernelAddress(&initrd_addr_alloc, mod_size) ) + PanicF("Failed to allocate kernel address space for the initrd"); + + // Map the physical frames onto our address space. + addr_t physfrom = module->mod_start; + addr_t mapat = initrd_addr_alloc.from; + for ( size_t i = 0; i < mod_size; i += Page::Size() ) { - if ( !Memory::LookUp(mapat + i, NULL, NULL) ) - continue; - addr_t addr = Memory::Unmap(mapat + i); - Page::Put(addr, PAGE_USAGE_WASNT_ALLOCATED); + if ( !Memory::Map(physfrom + i, mapat + i, PROT_KREAD | PROT_KWRITE) ) + PanicF("Unable to map the initrd into virtual memory"); } Memory::Flush(); + ctx->initrd = (uint8_t*) initrd_addr_alloc.from; + ctx->initrd_size = mod_size; + ctx->initrd_unmap_start = module->mod_start; + ctx->initrd_unmap_end = Page::AlignDown(module->mod_end); + + if ( sizeof(struct initrd_superblock) <= ctx->initrd_size && + !memcmp(ctx->initrd, "sortix-initrd-2", strlen("sortix-initrd-2")) ) + { + ExtractInitrd(desc, ctx); + } + else + { + Panic("Unsupported initrd format"); + } + + // Unmap the pages and return the physical frames for reallocation. + for ( size_t i = 0; i < mod_size; i += Page::Size() ) + UnmapInitrdPage(ctx, mapat + i); + Memory::Flush(); + + // Free the used virtual address space. FreeKernelAddress(&initrd_addr_alloc); - - ctx.amount_extracted = ctx.initrd_size; - initrd_progress(&ctx); - initrd_activity_done(); - - return true; } -} // namespace InitRD +void ExtractModules(struct multiboot_info* bootinfo, Ref root) +{ + struct multiboot_mod_list* modules = + (struct multiboot_mod_list*) (uintptr_t) bootinfo->mods_addr; + struct initrd_context ctx; + memset(&ctx, 0, sizeof(ctx)); + SetupKernelIOCtx(&ctx.ioctx); + for ( uint32_t i = 0; i < bootinfo->mods_count; i++ ) + ExtractModule(&modules[i], root, &ctx); +} + } // namespace Sortix diff --git a/kernel/initrd.h b/kernel/initrd.h index a064eac6..9b31a822 100644 --- a/kernel/initrd.h +++ b/kernel/initrd.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. This file is part of Sortix. @@ -18,7 +18,7 @@ Sortix. If not, see . initrd.h - Provides low-level access to a Sortix init ramdisk. + Extracts initrds into the initial memory filesystem. *******************************************************************************/ @@ -27,15 +27,13 @@ #include +struct multiboot_info; + namespace Sortix { class Descriptor; -namespace InitRD { - -bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref desc); - -} // namespace InitRD +void ExtractModules(struct multiboot_info* bootinfo, Ref root); } // namespace Sortix diff --git a/kernel/kernel.cpp b/kernel/kernel.cpp index 8eb5efd7..51d44711 100644 --- a/kernel/kernel.cpp +++ b/kernel/kernel.cpp @@ -111,8 +111,7 @@ static void BootThread(void* user); static void InitThread(void* user); static void SystemIdleThread(void* user); -addr_t initrd; -size_t initrdsize; +static multiboot_info_t* bootinfo; static char* init_cmdline; static char* cmdline_tokenize(char** saved) @@ -160,9 +159,10 @@ static char* cmdline_tokenize(char** saved) return data; } -extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) +extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p) { (void) magic; + bootinfo = bootinfo_p; // // Stage 1. Initialization of Early Environment. @@ -286,20 +286,6 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo) init_cmdline = parameter; } - initrd = 0; - initrdsize = 0; - - uint32_t* modules = (uint32_t*) (addr_t) bootinfo->mods_addr; - for ( uint32_t i = 0; i < bootinfo->mods_count; i++ ) - { - initrdsize = modules[2*i+1] - modules[2*i+0]; - initrd = (addr_t) modules[2*i+0]; - break; - } - - if ( !initrd ) - Panic("No init ramdisk provided"); - // Initialize the interrupt handler table and enable interrupts. Interrupt::Init(); @@ -436,11 +422,10 @@ static void BootThread(void* /*user*/) if ( iroot->link_raw(&ctx, "..", iroot) != 0 ) Panic("Unable to link /.. to /"); - // Install the initrd into our fresh RAM filesystem. - if ( !InitRD::ExtractFromPhysicalInto(initrd, initrdsize, droot) ) - Panic("Unable to extract initrd into RAM root filesystem. Your machine " - "needs more memory to boot using this initrd, as a rule of thumb " - "you need twice as much memory as the size of the initrd device."); + // Extract the initrds. + if ( bootinfo->mods_count == 0 ) + Panic("No initrd was loaded"); + ExtractModules(bootinfo, droot); // // Stage 5. Loading and Initializing Core Drivers.