feat: préparation de la gestion du CRAMFS depuis les sources de Linux

This commit is contained in:
Nicolas Hordé 2019-01-26 10:50:18 +01:00
parent acb06bc8a8
commit 5afa43629d
6 changed files with 476 additions and 3 deletions

83
include/cramfs.h Normal file
View File

@ -0,0 +1,83 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
/* Sources modifiées du noyau Linux cramfs_fs.h
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#include "types.h"
#ifndef _CRAMFS
#define _CRAMFS
#define CRAMFS_SIGNATURE "Compressed ROMFS"
#define CRAMFS_MODE_WIDTH 16
#define CRAMFS_UID_WIDTH 16
#define CRAMFS_SIZE_WIDTH 24
#define CRAMFS_GID_WIDTH 8
#define CRAMFS_NAMELEN_WIDTH 6
#define CRAMFS_OFFSET_WIDTH 26
#define CRAMFS_MAGIC 0x28cd3d45
#define CRAMFS_MAXPATHLEN (((1 << CRAMFS_NAMELEN_WIDTH) - 1) << 2)
#define PAD_SIZE 512
#define PAGE_CACHE_SIZE (4096)
typedef struct cramfs_inode {
u32 mode:CRAMFS_MODE_WIDTH;
u32 uid:CRAMFS_UID_WIDTH;
u32 size:CRAMFS_SIZE_WIDTH;
u32 gid:CRAMFS_GID_WIDTH;
u32 namelen:CRAMFS_NAMELEN_WIDTH;
u32 offset:CRAMFS_OFFSET_WIDTH;
} cramfs_inode;
typedef struct cramfs_info {
u32 crc;
u32 edition;
u32 blocks;
u32 files;
} cramfs_info;
typedef struct cramfs_super {
u32 magic; /* 0x28cd3d45 - random number */
u32 size; /* length in bytes */
u32 flags; /* feature flags */
u32 future; /* reserved for future use */
u8 signature[16]; /* "Compressed ROMFS" */
cramfs_info fsid; /* unique filesystem info */
u8 name[16]; /* user-defined name */
cramfs_inode root; /* root inode data */
} cramfs_super;
#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */
#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */
#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */
#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */
#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */
#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */
#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */
#define CRAMFS_FLAG_FSID_VERSION_2 0x00000001 /* fsid version #2 */
#define CRAMFS_FLAG_SORTED_DIRS 0x00000002 /* sorted dirs */
#define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */
#define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */
#define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */
#define CRAMFS_FLAG_EXT_BLOCK_POINTERS 0x00000800 /* block pointer extensions */
#define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \
| CRAMFS_FLAG_HOLES \
| CRAMFS_FLAG_WRONG_SIGNATURE \
| CRAMFS_FLAG_SHIFTED_ROOT_OFFSET \
| CRAMFS_FLAG_EXT_BLOCK_POINTERS )
#define CRAMFS_BLK_FLAG_UNCOMPRESSED (1 << 31)
#define CRAMFS_BLK_FLAG_DIRECT_PTR (1 << 30)
#define CRAMFS_BLK_FLAGS ( CRAMFS_BLK_FLAG_UNCOMPRESSED \
| CRAMFS_BLK_FLAG_DIRECT_PTR )
#define CRAMFS_BLK_DIRECT_PTR_SHIFT 2
u32 test_super(u8 *src, u32 length);
#endif

View File

@ -8,7 +8,7 @@
#define EPSILON 1E-40
#define degtorad(deg) (deg * PI / 180.0)
#define radtodeg(rad) (rad * 180.0 / PI)
u32 crc32(u32 inCrc32, u8 *buf, u32 size);
double cos(double x);
double sin(double x);
float cosf(float x);

325
lib/cramfs.c Normal file
View File

@ -0,0 +1,325 @@
/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
/* Quelques portions modifiée proviennent de cramfsck - check a cramfs file system
*
* Copyright (C) 2000-2002 Transmeta Corporation
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* 1999/12/03: Linus Torvalds (cramfs tester and unarchive program)
* 2000/06/03: Daniel Quinlan (CRC and length checking program)
* 2000/06/04: Daniel Quinlan (merged programs, added options, support
* for special files, preserve permissions and
* ownership, cramfs superblock v2, bogus mode
* test, pathname length test, etc.)
* 2000/06/06: Daniel Quinlan (support for holes, pretty-printing,
* symlink size test)
* 2000/07/11: Daniel Quinlan (file length tests, start at offset 0 or 512,
* fsck-compatible exit codes)
* 2000/07/15: Daniel Quinlan (initial support for block devices)
* 2002/01/10: Daniel Quinlan (additional checks, test more return codes,
* use read if mmap fails, standardize messages)
* 2015/06/09: Yves-Noel Weweler (support for ignoring errors, when
* extracting obscure cramfs files) */
#include "types.h"
#include "cramfs.h"
#include "boot.h"
#include "memory.h"
u8* initrambloc;
u8 start;
cramfs_super* super;
extern bootparams* allparams;
/*******************************************************************************/
/* Copie l'initram CRAMFS vers un malloc */
void remap_initram()
{
virtual_range_use_kernel(allparams->ramdiskaddr, allparams->ramdiskaddr, allparams->ramdisksize, PAGE_NOFLAG);
initrambloc=vmalloc(allparams->ramdisksize);
memcpy(allparams->ramdiskaddr,initrambloc,allparams->ramdisksize,0);
virtual_range_free_kernel(allparams->ramdiskaddr,allparams->ramdisksize);
}
/*******************************************************************************/
/* Lit l'inode et renvoie un pointeur grâce à vmalloc */
cramfs_inode *cramfs_iget(cramfs_inode * i)
{
cramfs_inode *inode = vmalloc(sizeof(cramfs_inode));
if (!inode)
return NULL;
*inode = *i;
return inode;
}
/*******************************************************************************/
/* Lit l'inode principal */
cramfs_inode *read_super(void)
{
u32 offset = super.root.offset << 2;
if (!S_ISDIR(super.root.mode))
return NULL; /* fichier */
if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((offset != sizeof(cramfs_super)) &&
(offset != PAD_SIZE + sizeof(cramfs_super))))
return NULL ; /*offset erronée */
return cramfs_iget(&super.root);
}
static int uncompress_block(void *src, int len)
{
int err;
stream.next_in = src;
stream.avail_in = len;
stream.next_out = (unsigned char *) outbuffer;
stream.avail_out = PAGE_CACHE_SIZE*2;
inflateReset(&stream);
if (len > PAGE_CACHE_SIZE*2) {
die(FSCK_UNCORRECTED, 0, "data block too large");
}
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
die(FSCK_UNCORRECTED, 0, "decompression error %p(%d): %s",
zError(err), src, len);
}
return stream.total_out;
}
static void do_uncompress(char *path, int fd, unsigned long offset, unsigned long size)
{
unsigned long curr = offset + 4 * ((size + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE);
do {
unsigned long out = PAGE_CACHE_SIZE;
unsigned long next = *(u32 *) romfs_read(offset);
if (next > end_data) {
end_data = next;
}
offset += 4;
if (curr == next) {
if (opt_verbose > 1) {
printf(" hole at %ld (%d)\n", curr, PAGE_CACHE_SIZE);
}
if (size < PAGE_CACHE_SIZE)
out = size;
memset(outbuffer, 0x00, out);
}
else {
if (opt_verbose > 1) {
printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr);
}
out = uncompress_block(romfs_read(curr), next - curr);
}
if (size >= PAGE_CACHE_SIZE) {
if (out != PAGE_CACHE_SIZE) {
die(FSCK_UNCORRECTED, 0, "non-block (%ld) bytes", out);
}
} else {
if (out != size) {
die(FSCK_UNCORRECTED, 0, "non-size (%ld vs %ld) bytes", out, size);
}
}
size -= out;
if (opt_extract) {
if (write(fd, outbuffer, out) < 0) {
die(FSCK_ERROR, 1, "write failed: %s", path);
}
}
curr = next;
} while (size);
}
tatic void change_file_status(char *path, struct cramfs_inode *i)
{
struct utimbuf epoch = { 0, 0 };
if (euid == 0) {
if (lchown(path, i->uid, i->gid) < 0) {
die(FSCK_ERROR, 1, "lchown failed: %s", path);
}
if (S_ISLNK(i->mode))
return;
if ((S_ISUID | S_ISGID) & i->mode) {
if (chmod(path, i->mode) < 0) {
die(FSCK_ERROR, 1, "chown failed: %s", path);
}
}
}
if (S_ISLNK(i->mode))
return;
if (utime(path, &epoch) < 0) {
die(FSCK_ERROR, 1, "utime failed: %s", path);
}
}
static void do_directory(char *path, struct cramfs_inode *i)
{
int pathlen = strlen(path);
int count = i->size;
unsigned long offset = i->offset << 2;
char *newpath = malloc(pathlen + 256);
if (!newpath) {
die(FSCK_ERROR, 1, "malloc failed");
}
if (offset == 0 && count != 0) {
die(FSCK_UNCORRECTED, 0, "directory inode has zero offset and non-zero size: %s", path);
}
if (offset != 0 && offset < start_dir) {
start_dir = offset;
}
/* TODO: Do we need to check end_dir for empty case? */
memcpy(newpath, path, pathlen);
newpath[pathlen] = '/';
pathlen++;
if (opt_verbose) {
print_node('d', i, path);
}
if (opt_extract) {
if (mkdir(path, i->mode) < 0) {
die(FSCK_ERROR, 1, "mkdir failed: %s", path);
}
change_file_status(path, i);
}
while (count > 0) {
struct cramfs_inode *child = iget(offset);
int size;
int newlen = child->namelen << 2;
size = sizeof(struct cramfs_inode) + newlen;
count -= size;
offset += sizeof(struct cramfs_inode);
memcpy(newpath + pathlen, romfs_read(offset), newlen);
newpath[pathlen + newlen] = 0;
if (newlen == 0) {
die(FSCK_UNCORRECTED, 0, "filename length is zero");
}
if ((pathlen + newlen) - strlen(newpath) > 3) {
die(FSCK_UNCORRECTED, 0, "bad filename length");
}
expand_fs(newpath, child);
offset += newlen;
if (offset <= start_dir) {
die(FSCK_UNCORRECTED, 0, "bad inode offset");
}
if (offset > end_dir) {
end_dir = offset;
}
iput(child); /* free(child) */
}
free(newpath);
}
void do_file(u8 *path, cramfs_inode *i)
{
u32 offset = i->offset << 2;
if (offset == 0 && i->size != 0)
return /*null de taille non nulle */
if (i->size == 0 && offset != 0)
return /*non null de taille nulle */
if (offset != 0 && offset < start_data)
start_data = offset;
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode);
if (i->size)
do_uncompress(path, fd, offset, i->size);
close(fd);
change_file_status(path, i);
}
void expand_fs(u8 *path, cramfs_inode *inode)
{
if (S_ISDIR(inode->mode)) {
do_directory(path, inode);
}
else if (S_ISREG(inode->mode)) {
do_file(path, inode);
}
else if (S_ISLNK(inode->mode)) {
/*do_symlink(path, inode);*/
}
else {
/*do_special_inode(path, inode);*/
}
}
/*******************************************************************************/
/* Vérification d'une image cramfs */
/* ERREURS :
/* 1=taille du super bloc trop petite */
/* 2=pas de magic */
/* 3=pas géré */
/* 4=superbloc trop petit */
/* 5=aucune fichier */
/* 6=taille entrée des fichiers trop petite */
/* 7=taille entrée des fichiers trop grande */
/* 8=version de cramfs non supportée */
/* 9=crc erroné */
u32 test_super(u8 *src, u32 length) {
super=(cramfs_super*)src;
start = 0xFF;
if (length < sizeof(cramfs_super)) {
return 1;
}
if (super->magic == CRAMFS_MAGIC) {
start = 0;
}
else if (length >= (PAD_SIZE + sizeof(super))) {
if (super->magic == CRAMFS_MAGIC) {
start = PAD_SIZE;
}
}
else
return 2;
if (super->flags & ~CRAMFS_SUPPORTED_FLAGS)
return 3;
if (super->size < PAGE_CACHE_SIZE)
return 4;
if (super->flags & CRAMFS_FLAG_FSID_VERSION_2) {
if (super->fsid.files == 0)
return 5;
if (length < super->size)
return 6;
else if (length > super->size)
return 7;
}
else
return 8;
u32 oldcrc=super->fsid.crc;
super->fsid.crc = crc32(0, 0, 0);
u32 newcrc=crc32(0,src+*start,super->size-*start);
super->fsid.crc = oldcrc;
if (newcrc!=oldcrc)
return 9;
return NULL;
}

View File

@ -5,6 +5,60 @@
#include "timer.h"
#include "math.h"
/*******************************************************************************/
/* Calcule un checksum 32 bits */
u32 crc32(u32 inCrc32, u8 *buf, u32 size)
{
static const u32 crcTable[256] = {
0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,
0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,
0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,
0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,
0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,
0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,
0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,
0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,
0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,
0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,
0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,
0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,
0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,
0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,
0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,
0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,
0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,
0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,
0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,
0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,
0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,
0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,
0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,
0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,
0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,
0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,
0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,
0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,
0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D };
u32 crc32;
u8 *byteBuf;
u32 i;
crc32 = inCrc32 ^ 0xFFFFFFFF;
byteBuf = (u8*) buf;
for (i=0; i < size; i++) {
crc32 = (crc32 >> 8) ^ crcTable[ (crc32 ^ byteBuf[i]) & 0xFF ];
}
return( crc32 ^ 0xFFFFFFFF );
}
/*******************************************************************************/
/* Arithmétique 64 bits */

View File

@ -16,6 +16,7 @@ extern bootparams* allparams;
/*******************************************************************************/
/* Erreur fatale */
void panic(u8 * string)
{
printf("KERNEL PANIC: %s\r\nSysteme arrete...\n");

View File

@ -17,6 +17,7 @@
#include "memory.h"
#include "system.h"
#include "boot.h"
#include "cramfs.h"
static u8 warnmsg[] =
"\033[150C\033[8D\033[37m\033[1m[ \033[36mNON\033[37m ]\033[0m";
@ -28,6 +29,7 @@ static u8 key = 0;
extern wrapper_timer;
extern wrapper_interruption20;
extern u8* initrambloc;
bootparams* allparams;
@ -63,10 +65,14 @@ void main(bootparams** params)
print("\033[2J\r\n\000");
logo();
print("\033[37m\033[0m -Initilisation de la memoire virtuelle");
print("\033[37m\033[0m -Initialisation de la memoire virtuelle");
initgdt(&&next);
next:
initpaging(*allparams);
initpaging();
ok();
print("\033[37m\033[0m -Remapping de l'arborescence de demarrage et du VESA");
remap_initram();
remap_memory(VESA_FBMEM);
ok();
@ -110,6 +116,10 @@ next:
finit();
ok();
printf(" -Initialisation de l'arborescence");
test_super(initrambloc ,allparams->ramdisksize);
ok();
retry:
sti();
shell();