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.