Relicense Sortix to the ISC license.
I hereby relicense all my work on Sortix under the ISC license as below.
All Sortix contributions by other people are already under this license,
are not substantial enough to be copyrightable, or have been removed.
All imported code from other projects is compatible with this license.
All GPL licensed code from other projects had previously been removed.
Copyright 2011-2016 Jonas 'Sortie' Termansen and contributors.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2016-03-02 22:38:16 +00:00
|
|
|
/*
|
2023-07-15 14:43:27 +00:00
|
|
|
* Copyright (c) 2011-2016, 2023 Jonas 'Sortie' Termansen.
|
Relicense Sortix to the ISC license.
I hereby relicense all my work on Sortix under the ISC license as below.
All Sortix contributions by other people are already under this license,
are not substantial enough to be copyrightable, or have been removed.
All imported code from other projects is compatible with this license.
All GPL licensed code from other projects had previously been removed.
Copyright 2011-2016 Jonas 'Sortie' Termansen and contributors.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2016-03-02 22:38:16 +00:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*
|
|
|
|
* initrd.cpp
|
|
|
|
* Extracts initrds into the initial memory filesystem.
|
|
|
|
*/
|
2011-08-27 15:41:35 +00:00
|
|
|
|
2013-05-16 19:35:49 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
2016-03-07 16:30:04 +00:00
|
|
|
#include <libgen.h>
|
2014-05-09 23:06:07 +00:00
|
|
|
#include <stdarg.h>
|
2013-05-16 19:35:49 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
2015-11-04 23:36:22 +00:00
|
|
|
#include <stdlib.h>
|
2013-05-16 19:35:49 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <timespec.h>
|
|
|
|
|
2014-04-29 21:52:52 +00:00
|
|
|
#include <sortix/dirent.h>
|
2013-05-16 19:35:49 +00:00
|
|
|
#include <sortix/fcntl.h>
|
|
|
|
#include <sortix/mman.h>
|
|
|
|
#include <sortix/stat.h>
|
2015-11-04 23:36:22 +00:00
|
|
|
#include <sortix/tar.h>
|
2013-05-16 19:35:49 +00:00
|
|
|
|
2013-02-09 17:32:45 +00:00
|
|
|
#include <sortix/kernel/addralloc.h>
|
2012-08-07 22:19:44 +00:00
|
|
|
#include <sortix/kernel/descriptor.h>
|
2013-10-27 00:42:10 +00:00
|
|
|
#include <sortix/kernel/fsfunc.h>
|
|
|
|
#include <sortix/kernel/ioctx.h>
|
|
|
|
#include <sortix/kernel/kernel.h>
|
2012-03-23 18:36:51 +00:00
|
|
|
#include <sortix/kernel/memorymanagement.h>
|
2012-09-23 11:27:42 +00:00
|
|
|
#include <sortix/kernel/string.h>
|
2013-01-08 23:41:35 +00:00
|
|
|
#include <sortix/kernel/syscall.h>
|
2013-10-27 00:42:10 +00:00
|
|
|
#include <sortix/kernel/vnode.h>
|
2013-01-08 23:41:35 +00:00
|
|
|
|
2012-03-23 18:36:51 +00:00
|
|
|
#include "initrd.h"
|
2015-11-04 13:06:17 +00:00
|
|
|
#include "multiboot.h"
|
2011-08-27 15:41:35 +00:00
|
|
|
|
2012-03-23 18:36:51 +00:00
|
|
|
namespace Sortix {
|
|
|
|
|
2014-05-08 23:32:51 +00:00
|
|
|
struct initrd_context
|
2011-08-27 15:41:35 +00:00
|
|
|
{
|
2014-05-08 23:32:51 +00:00
|
|
|
uint8_t* initrd;
|
|
|
|
size_t initrd_size;
|
2015-11-04 13:06:17 +00:00
|
|
|
addr_t initrd_unmap_start;
|
|
|
|
addr_t initrd_unmap_end;
|
2014-05-08 23:32:51 +00:00
|
|
|
ioctx_t ioctx;
|
|
|
|
};
|
|
|
|
|
2015-11-04 13:06:17 +00:00
|
|
|
// 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)
|
2014-05-09 23:06:07 +00:00
|
|
|
{
|
2015-11-04 13:06:17 +00:00
|
|
|
if ( !Memory::LookUp(vaddr, NULL, NULL) )
|
2014-05-09 23:06:07 +00:00
|
|
|
return;
|
2015-11-04 13:06:17 +00:00
|
|
|
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);
|
2014-05-09 23:06:07 +00:00
|
|
|
}
|
|
|
|
|
2015-11-04 23:36:22 +00:00
|
|
|
struct TAR
|
|
|
|
{
|
|
|
|
unsigned char* tar_file;
|
|
|
|
size_t tar_file_size;
|
|
|
|
size_t next_offset;
|
|
|
|
size_t offset;
|
|
|
|
size_t data_offset;
|
|
|
|
char* name;
|
|
|
|
char* linkname;
|
|
|
|
unsigned char* data;
|
|
|
|
size_t size;
|
|
|
|
mode_t mode;
|
|
|
|
char typeflag;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void OpenTar(TAR* TAR, unsigned char* tar_file, size_t tar_file_size)
|
|
|
|
{
|
|
|
|
memset(TAR, 0, sizeof(*TAR));
|
|
|
|
TAR->tar_file = tar_file;
|
|
|
|
TAR->tar_file_size = tar_file_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CloseTar(TAR* TAR)
|
|
|
|
{
|
|
|
|
free(TAR->name);
|
|
|
|
free(TAR->linkname);
|
|
|
|
memset(TAR, 0, sizeof(*TAR));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ReadTar(TAR* TAR)
|
|
|
|
{
|
|
|
|
free(TAR->name);
|
|
|
|
free(TAR->linkname);
|
|
|
|
TAR->name = NULL;
|
|
|
|
TAR->linkname = NULL;
|
|
|
|
while ( true )
|
|
|
|
{
|
|
|
|
if ( TAR->tar_file_size - TAR->next_offset < sizeof(struct TAR) )
|
|
|
|
return false;
|
|
|
|
TAR->offset = TAR->next_offset;
|
|
|
|
struct tar* tar = (struct tar*) (TAR->tar_file + TAR->offset);
|
2018-03-05 22:13:29 +00:00
|
|
|
if ( tar->size[sizeof(tar->size) - 1] != '\0' &&
|
|
|
|
tar->size[sizeof(tar->size) - 1] != ' ' )
|
2015-11-04 23:36:22 +00:00
|
|
|
return false;
|
|
|
|
size_t size = strtoul(tar->size, NULL, 8);
|
|
|
|
size_t dist = sizeof(struct tar) + -(-size & ~((size_t) 512 - 1));
|
|
|
|
if ( TAR->tar_file_size - TAR->offset < dist )
|
|
|
|
return false;
|
|
|
|
TAR->next_offset = TAR->offset + dist;
|
|
|
|
TAR->data_offset = TAR->offset + 512;
|
|
|
|
TAR->data = TAR->tar_file + TAR->data_offset;
|
|
|
|
TAR->size = size;
|
2018-03-05 22:13:29 +00:00
|
|
|
if ( tar->mode[sizeof(tar->mode) - 1] != '\0' &&
|
|
|
|
tar->mode[sizeof(tar->mode) - 1] != ' ' )
|
2015-11-04 23:36:22 +00:00
|
|
|
return false;
|
|
|
|
TAR->mode = strtoul(tar->mode, NULL, 8) & 07777;
|
|
|
|
TAR->typeflag = tar->typeflag;
|
|
|
|
// TODO: Things like modified time and other meta data!
|
|
|
|
if ( tar->typeflag == 'L' )
|
|
|
|
{
|
|
|
|
free(TAR->name);
|
|
|
|
if ( !(TAR->name = (char*) malloc(size + 1)) )
|
|
|
|
Panic("initrd tar malloc failure");
|
|
|
|
memcpy(TAR->name, TAR->data, size);
|
|
|
|
TAR->name[size] = '\0';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( tar->typeflag == 'g' )
|
|
|
|
{
|
|
|
|
// TODO: Implement pax extensions.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( tar->typeflag == 'x' )
|
|
|
|
{
|
|
|
|
// TODO: Implement pax extensions.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( !tar->name[0] )
|
|
|
|
continue;
|
|
|
|
if ( !TAR->name )
|
|
|
|
{
|
|
|
|
if ( tar->prefix[0] )
|
|
|
|
{
|
|
|
|
size_t prefix_len = strnlen(tar->prefix, sizeof(tar->prefix));
|
|
|
|
size_t name_len = strnlen(tar->name, sizeof(tar->name));
|
|
|
|
size_t name_size = prefix_len + 1 + name_len + 1;
|
|
|
|
if ( !(TAR->name = (char*) malloc(name_size)) )
|
|
|
|
Panic("initrd tar malloc failure");
|
|
|
|
memcpy(TAR->name, tar->prefix, prefix_len);
|
|
|
|
TAR->name[prefix_len] = '/';
|
|
|
|
memcpy(TAR->name + prefix_len + 1, tar->name, name_len);
|
|
|
|
TAR->name[prefix_len + 1 + name_len] = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TAR->name = (char*) strndup(tar->name, sizeof(tar->name));
|
|
|
|
if ( !TAR->name )
|
|
|
|
Panic("initrd tar malloc failure");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !TAR->linkname )
|
|
|
|
{
|
|
|
|
TAR->linkname = (char*) strndup(tar->linkname, sizeof(tar->linkname));
|
|
|
|
if ( !TAR->linkname )
|
|
|
|
Panic("initrd tar malloc failure");
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExtractTarObject(Ref<Descriptor> desc,
|
|
|
|
struct initrd_context* ctx,
|
|
|
|
TAR* TAR)
|
|
|
|
{
|
2018-03-05 22:13:29 +00:00
|
|
|
if ( TAR->typeflag == '0' || TAR->typeflag == 0 )
|
2015-11-04 23:36:22 +00:00
|
|
|
{
|
|
|
|
int oflags = O_WRITE | O_CREATE | O_TRUNC;
|
|
|
|
Ref<Descriptor> file(desc->open(&ctx->ioctx, TAR->name, oflags, TAR->mode));
|
|
|
|
if ( !file )
|
|
|
|
PanicF("%s: %m", TAR->name);
|
|
|
|
if ( file->truncate(&ctx->ioctx, TAR->size) != 0 )
|
|
|
|
PanicF("truncate: %s: %m", TAR->name);
|
|
|
|
size_t sofar = 0;
|
|
|
|
while ( sofar < TAR->size )
|
|
|
|
{
|
|
|
|
size_t left = TAR->size - sofar;
|
|
|
|
size_t chunk = 1024 * 1024;
|
|
|
|
size_t count = left < chunk ? left : chunk;
|
|
|
|
ssize_t numbytes = file->write(&ctx->ioctx, TAR->data + sofar, count);
|
|
|
|
if ( numbytes <= 0 )
|
|
|
|
PanicF("write: %s: %m", TAR->name);
|
|
|
|
sofar += numbytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( TAR->typeflag == '1' )
|
|
|
|
{
|
|
|
|
Ref<Descriptor> dest(desc->open(&ctx->ioctx, TAR->linkname, O_READ, 0));
|
|
|
|
if ( !dest )
|
|
|
|
PanicF("%s: %m", TAR->linkname);
|
|
|
|
if ( desc->link(&ctx->ioctx, TAR->name, dest) != 0 )
|
|
|
|
PanicF("link: %s -> %s: %m", TAR->linkname, TAR->name);
|
|
|
|
}
|
|
|
|
else if ( TAR->typeflag == '2' )
|
|
|
|
{
|
|
|
|
if ( desc->symlink(&ctx->ioctx, TAR->linkname, TAR->name) != 0 )
|
|
|
|
PanicF("symlink: %s: %m", TAR->name);
|
|
|
|
}
|
|
|
|
else if ( TAR->typeflag == '5' )
|
|
|
|
{
|
|
|
|
if ( desc->mkdir(&ctx->ioctx, TAR->name, TAR->mode) && errno != EEXIST )
|
|
|
|
PanicF("mkdir: %s: %m", TAR->name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Log::PrintF("kernel: initrd: %s: Unsupported tar filetype '%c'\n",
|
|
|
|
TAR->name, TAR->typeflag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExtractTar(Ref<Descriptor> desc, struct initrd_context* ctx)
|
|
|
|
{
|
|
|
|
TAR TAR;
|
|
|
|
OpenTar(&TAR, ctx->initrd, ctx->initrd_size);
|
|
|
|
while ( ReadTar(&TAR) )
|
|
|
|
ExtractTarObject(desc, ctx, &TAR);
|
|
|
|
CloseTar(&TAR);
|
|
|
|
}
|
|
|
|
|
2016-03-07 16:30:04 +00:00
|
|
|
static int ExtractTo_mkdir(Ref<Descriptor> desc, ioctx_t* ctx,
|
|
|
|
const char* path, mode_t mode)
|
|
|
|
{
|
|
|
|
int saved_errno = errno;
|
|
|
|
if ( !desc->mkdir(ctx, path, mode) )
|
|
|
|
return 0;
|
|
|
|
if ( errno == ENOENT )
|
|
|
|
{
|
|
|
|
char* prev = strdup(path);
|
|
|
|
if ( !prev )
|
|
|
|
return -1;
|
|
|
|
int status = ExtractTo_mkdir(desc, ctx, dirname(prev), mode | 0500);
|
|
|
|
free(prev);
|
|
|
|
if ( status < 0 )
|
|
|
|
return -1;
|
|
|
|
errno = saved_errno;
|
|
|
|
if ( !desc->mkdir(ctx, path, mode) )
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ( errno == EEXIST )
|
|
|
|
return errno = saved_errno, 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ExtractTo(Ref<Descriptor> desc,
|
|
|
|
struct initrd_context* ctx,
|
2018-09-26 21:31:48 +00:00
|
|
|
const char* path,
|
|
|
|
int extra_oflags)
|
2016-03-07 16:30:04 +00:00
|
|
|
{
|
2018-09-26 21:31:48 +00:00
|
|
|
int oflags = O_WRITE | O_CREATE | extra_oflags;
|
2016-03-07 16:30:04 +00:00
|
|
|
Ref<Descriptor> file(desc->open(&ctx->ioctx, path, oflags, 0644));
|
|
|
|
if ( !file && errno == ENOENT )
|
|
|
|
{
|
|
|
|
char* prev = strdup(path);
|
|
|
|
if ( !prev )
|
|
|
|
PanicF("%s: strdup: %m", path);
|
2017-03-18 15:40:57 +00:00
|
|
|
if ( ExtractTo_mkdir(desc, &ctx->ioctx, dirname(prev), 0755) < 0 )
|
2016-03-07 16:30:04 +00:00
|
|
|
PanicF("%s: mkdir -p: %s: %m", path, prev);
|
|
|
|
free(prev);
|
|
|
|
file = desc->open(&ctx->ioctx, path, oflags, 0644);
|
|
|
|
}
|
|
|
|
if ( !file )
|
2018-09-26 21:31:48 +00:00
|
|
|
{
|
|
|
|
if ( errno == EEXIST && (oflags & O_EXCL) )
|
|
|
|
return;
|
2016-03-07 16:30:04 +00:00
|
|
|
PanicF("%s: %m", path);
|
2018-09-26 21:31:48 +00:00
|
|
|
}
|
|
|
|
if ( !(oflags & O_APPEND) )
|
|
|
|
{
|
|
|
|
if ( file->truncate(&ctx->ioctx, ctx->initrd_size) != 0 )
|
|
|
|
PanicF("truncate: %s: %m", path);
|
|
|
|
}
|
2016-03-07 16:30:04 +00:00
|
|
|
size_t sofar = 0;
|
|
|
|
while ( sofar < ctx->initrd_size )
|
|
|
|
{
|
|
|
|
size_t left = ctx->initrd_size - sofar;
|
|
|
|
size_t chunk = 1024 * 1024;
|
|
|
|
size_t count = left < chunk ? left : chunk;
|
|
|
|
ssize_t numbytes = file->write(&ctx->ioctx, ctx->initrd + sofar, count);
|
|
|
|
if ( numbytes <= 0 )
|
|
|
|
PanicF("write: %s: %m", path);
|
|
|
|
sofar += numbytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-04 13:06:17 +00:00
|
|
|
static void ExtractModule(struct multiboot_mod_list* module,
|
|
|
|
Ref<Descriptor> desc,
|
|
|
|
struct initrd_context* ctx)
|
|
|
|
{
|
|
|
|
size_t mod_size = module->mod_end - module->mod_start;
|
2016-03-07 16:30:04 +00:00
|
|
|
const char* cmdline = (const char*) (uintptr_t) module->cmdline;
|
2013-03-12 16:40:33 +00:00
|
|
|
|
2016-08-20 00:27:33 +00:00
|
|
|
// Ignore the random seed.
|
|
|
|
if ( !strcmp(cmdline, "--random-seed") )
|
|
|
|
return;
|
|
|
|
|
2015-11-04 13:06:17 +00:00
|
|
|
// 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() )
|
2013-03-12 16:40:33 +00:00
|
|
|
{
|
2015-11-04 13:06:17 +00:00
|
|
|
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);
|
|
|
|
|
2016-12-29 18:39:52 +00:00
|
|
|
const unsigned char xz_magic[] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
|
|
|
|
const unsigned char bzip2_magic[] = { 'B', 'Z' };
|
|
|
|
const unsigned char gz_magic[] = { 0x1F, 0x8B };
|
|
|
|
|
2018-09-26 21:18:16 +00:00
|
|
|
if ( !strncmp(cmdline, "--to ", strlen("--to ")) ||
|
|
|
|
!strncmp(cmdline, "--to=", strlen("--to=")) )
|
2018-09-26 21:31:48 +00:00
|
|
|
ExtractTo(desc, ctx, cmdline + strlen("--to "), O_TRUNC);
|
|
|
|
else if ( !strncmp(cmdline, "--append-to ", strlen("--append-to ")) ||
|
|
|
|
!strncmp(cmdline, "--append-to=", strlen("--append-to=")) )
|
|
|
|
ExtractTo(desc, ctx, cmdline + strlen("--append-to "), O_APPEND);
|
|
|
|
else if ( !strncmp(cmdline, "--create-to ", strlen("--create-to ")) ||
|
|
|
|
!strncmp(cmdline, "--create-to=", strlen("--create-to=")) )
|
|
|
|
ExtractTo(desc, ctx, cmdline + strlen("--create-to "), O_EXCL);
|
2023-07-16 12:56:31 +00:00
|
|
|
// TODO: After releasing Sortix 1.1, remove this nice error message.
|
|
|
|
else if ( strlen("sortix-initrd-2") <= ctx->initrd_size &&
|
2016-03-07 16:30:04 +00:00
|
|
|
!memcmp(ctx->initrd, "sortix-initrd-2", strlen("sortix-initrd-2")) )
|
2023-07-16 12:56:31 +00:00
|
|
|
Panic("The sortix-initrd-2 format is no longer supported");
|
2015-11-04 23:36:22 +00:00
|
|
|
else if ( sizeof(struct tar) <= ctx->initrd_size &&
|
|
|
|
!memcmp(ctx->initrd + offsetof(struct tar, magic), "ustar", 5) )
|
2023-07-15 14:43:27 +00:00
|
|
|
ExtractTar(desc, ctx);
|
2016-12-29 18:39:52 +00:00
|
|
|
else if ( sizeof(xz_magic) <= ctx->initrd_size &&
|
|
|
|
!memcmp(ctx->initrd, xz_magic, sizeof(xz_magic)) )
|
|
|
|
Panic("Bootloader failed to decompress an xz initrd, "
|
|
|
|
"or try the --to <path> option");
|
|
|
|
else if ( sizeof(gz_magic) <= ctx->initrd_size &&
|
|
|
|
!memcmp(ctx->initrd, gz_magic, sizeof(gz_magic)) )
|
|
|
|
Panic("Bootloader failed to decompress a gzip initrd, "
|
|
|
|
"or try the --to <path> option");
|
|
|
|
else if ( sizeof(bzip2_magic) <= ctx->initrd_size &&
|
|
|
|
!memcmp(ctx->initrd, bzip2_magic, sizeof(bzip2_magic)) )
|
|
|
|
Panic("Bootloader failed to decompress a bzip2 initrd, "
|
|
|
|
"or try the --to <path> option");
|
2015-11-04 13:06:17 +00:00
|
|
|
else
|
2016-03-07 16:30:04 +00:00
|
|
|
Panic("Unsupported initrd format, or try the --to <path> option");
|
2015-11-04 13:06:17 +00:00
|
|
|
|
|
|
|
// 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);
|
2013-03-12 16:40:33 +00:00
|
|
|
Memory::Flush();
|
|
|
|
|
|
|
|
// Free the used virtual address space.
|
|
|
|
FreeKernelAddress(&initrd_addr_alloc);
|
2015-11-04 13:06:17 +00:00
|
|
|
}
|
2014-04-29 21:52:52 +00:00
|
|
|
|
2015-11-04 13:06:17 +00:00
|
|
|
void ExtractModules(struct multiboot_info* bootinfo, Ref<Descriptor> 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);
|
2013-03-12 16:40:33 +00:00
|
|
|
}
|
|
|
|
|
2012-03-23 18:36:51 +00:00
|
|
|
} // namespace Sortix
|