1
0
Fork 0
mirror of https://gitlab.com/bztsrc/bootboot.git synced 2023-02-13 20:54:32 -05:00

Added echfs support

This commit is contained in:
bzt 2021-03-17 16:04:05 +01:00
parent 90f4e071b5
commit 6e8cb41f36
17 changed files with 350 additions and 10 deletions

View file

@ -288,6 +288,42 @@ file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
return ret;
}
/**
* EchFS
* http://github.com/echfs/echfs
*/
file_t ech_initrd(unsigned char *initrd_p, char *kernel)
{
uint64_t parent = 0xffffffffffffffffUL, n;
unsigned char *ptr;
char *end, *fn;
int k = 0;
file_t ret = { NULL, 0 };
if(initrd_p==NULL || kernel==NULL || memcmp(initrd_p+4,"_ECH_FS_",8))
return ret;
DBG(" * EchFS ");
DBG(kernel);
DBG("\n");
memcpy(&k, initrd_p + 28, 4);
memcpy(&n, initrd_p + 12, 8);
ptr = initrd_p + (((n * 8 + k - 1) / k) + 16) * k;
for(end = fn = kernel; *end && *end != '/'; end++);
while(*((uint64_t*)ptr)) {
if(*((uint64_t*)ptr) == parent && !memcmp(ptr + 9, fn, end - fn) && !ptr[9 + end - fn]) {
parent = *((uint64_t*)(ptr + 240));
if(!*end) {
ret.size=*((uint64_t*)(ptr + 248));
ret.ptr=(uint8_t*)(initrd_p + parent * k);
break;
}
end++;
for(fn = end; *end && *end != '/'; end++);
}
ptr += 256;
}
return ret;
}
/**
* Static file system drivers registry
*/
@ -297,5 +333,6 @@ file_t (*fsdrivers[]) (unsigned char *, char *) = {
tar_initrd,
sfs_initrd,
jamesm_initrd,
ech_initrd,
NULL
};

Binary file not shown.

Binary file not shown.

BIN
dist/bootboot.bin vendored

Binary file not shown.

BIN
dist/bootboot.efi vendored

Binary file not shown.

BIN
dist/bootboot.img vendored

Binary file not shown.

BIN
dist/bootboot.rom vendored

Binary file not shown.

View file

@ -6,7 +6,8 @@ BOOTBOOT Bootolható Lemezkép Készítő
Ez egy minden az egyben, többplatformos, függőség nélküli lemezkép kreáló (na jó, zlib kell neki, de az statikusan bele van
forgatva). Egy lemezkonfigurációt kell megadni neki JSON-ben, és létrehozza az ESP FAT boot partíciót a szükséges betöltő
fájlokkal, GPT táblával, PMBR-el, stb. Továbbá képes létrehozni az induló memórialemezképet egy könyvtár tartalmából (jelenleg
`cpio`, `tar`, `jamesm` (James Molloy initrdje) és az `FS/Z` támogatott, de a kód úgy lett megírva, hogy könnyű legyen bővíteni).
`cpio`, `tar`, `jamesm` (James Molloy initrdje), `echfs` és az `FS/Z` támogatott, de a kód úgy lett megírva, hogy könnyű legyen
bővíteni).
A kigenerált képet leellenőriztem fdisk-el, valamint a gdisk verify funkciójával. A FAT partíció tesztelve lett fsck.vfat-al
és UEFI förmverrel, továbbá Raspberry Pi-n. Az ISO9660-es rész iat-vel (ISO9660 Analyzer Tool) és Linux mounttal lett tesztelve.

View file

@ -5,8 +5,8 @@ See [BOOTBOOT Protocol](https://gitlab.com/bztsrc/bootboot) for common details.
This is an all-in-one, multiplatform, dependency-free disk image creator tool. You pass a disk configuration to it in a very
flexible JSON, and it generates ESP FAT boot partition with the required loader files, GPT partitioning table, PMBR, etc. It
also creates an initrd from a directory (currently `cpio`, `tar`, `jamesm` (James Molloy's initrd) and `FS/Z` supported, but
the code is written in a way that it is easily expandable).
also creates an initrd from a directory (currently `cpio`, `tar`, `jamesm` (James Molloy's initrd), `echfs` and `FS/Z`
supported, but the code is written in a way that it is easily expandable).
The generated image was tested with fdisk, and with the verify function of gdisk. The FAT partition was tested with fsck.vfat
and with TianoCore UEFI firmware and on Raspberry Pi. The ISO9660 part tested with iat (ISO9660 Analyzer Tool) and Linux mount.

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
extern unsigned char binary_boot_bin[512];
extern unsigned char binary_bootboot_bin[13312];
extern unsigned char binary_bootboot_efi[103073];
extern unsigned char binary_bootboot_efi[103614];
extern unsigned char binary_bootboot_img[34888];
extern unsigned char binary_bootboot_rv64[8192];
extern unsigned char binary_LICENCE_broadcom[1594];

170
mkbootimg/ech.c Normal file
View file

@ -0,0 +1,170 @@
/*
* mkbootimg/ech.c
*
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This file is part of the BOOTBOOT Protocol package.
* @brief a very minimal echfs driver which is much easier to use than echfs-utils
*
*/
#include "main.h"
typedef struct {
uint64_t parent_id;
uint8_t type;
char name[201];
uint64_t atime;
uint64_t mtime;
uint16_t perms;
uint16_t owner;
uint16_t group;
uint64_t ctime;
uint64_t payload;
uint64_t size;
}__attribute__((packed)) ech_entry_t;
ech_entry_t *ech_ents = NULL;
int ech_numents, ech_maxents;
uint8_t *ech_data = NULL, ech_uuid[16];
uint64_t ech_size;
uint64_t ech_numblk;
void ech_open(gpt_t *gpt_entry)
{
if(gpt) {
if((gpt_entry->last - gpt_entry->start) < 1) { fprintf(stderr,"mkbootimg: %s\r\n", lang[ERR_NOSIZE]); exit(1); }
memcpy(ech_uuid, &gpt_entry->guid, 16);
ech_numblk = gpt_entry->last - gpt_entry->start + 1;
ech_maxents = (ech_numblk * 5 / 100) * 512 / sizeof(ech_entry_t);
} else {
memcpy(ech_uuid, "INITRD", 6);
memset(ech_uuid + 6, 0, 10);
ech_numblk = 0;
ech_maxents = 0;
}
ech_numents = 0;
ech_size = 0;
}
void ech_add(struct stat *st, char *name, unsigned char *content, int size)
{
uint64_t parent = UINT64_C(0xffffffffffffffff);
int i, j;
char *end, *fn = strrchr(name, '/');
if(!fn) fn = name; else fn++;
if(!strcmp(fn, ".") || !strcmp(fn, "..")) return;
if(!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) return;
fn = name;
end = strchr(name, '/');
if(!end) end = name + strlen(name);
for(i = 0; i < ech_numents; i++) {
if(ech_ents[i].parent_id == parent && !memcmp(ech_ents[i].name, fn, end - fn) && !ech_ents[i].name[end - fn]) {
parent = ech_ents[i].payload;
fn = end + 1;
end = *end ? strchr(fn, '/') : NULL;
if(!end) { end = fn + strlen(name); break; }
}
}
if(ech_maxents && ech_numents + 1 >= ech_maxents) { fprintf(stderr,"mkbootimg: %s\r\n",lang[ERR_TOOMANY]); exit(1); }
ech_ents = (ech_entry_t*)realloc(ech_ents, (ech_numents + 1) * sizeof(ech_entry_t));
if(!ech_ents) { fprintf(stderr,"mkbootimg: %s\r\n",lang[ERR_MEM]); exit(1); }
memset(&ech_ents[ech_numents], 0, sizeof(ech_entry_t));
ech_ents[ech_numents].parent_id = parent;
memcpy(ech_ents[ech_numents].name, fn, end - fn);
ech_ents[ech_numents].atime = st->st_atime;
ech_ents[ech_numents].mtime = st->st_mtime;
ech_ents[ech_numents].ctime = st->st_ctime;
ech_ents[ech_numents].perms = st->st_mode & 0xFFF;
if(S_ISDIR(st->st_mode)) {
ech_ents[ech_numents].type = 1;
ech_ents[ech_numents].payload = ech_numents + 1;
} else {
ech_ents[ech_numents].size = size;
ech_ents[ech_numents].payload = ech_size / 512;
j = (size + 511) & ~511;
if(j > 0) {
ech_data = (uint8_t*)realloc(ech_data, ech_size + j);
if(!ech_ents) { fprintf(stderr,"mkbootimg: %s\r\n",lang[ERR_MEM]); exit(1); }
memcpy(ech_data + ech_size, content, size);
ech_size += j;
}
}
ech_numents++;
}
void ech_close()
{
ech_entry_t *ent;
uint64_t offs, *ptr, i, j;
if(!ech_numblk) {
ech_maxents = ech_numents;
ech_numblk = 16 + (ech_numents * sizeof(ech_entry_t) + 511 + ech_size) / 512;
ech_numblk += (ech_numblk * 8 + 511) / 512;
}
offs = 16 + ((ech_maxents * sizeof(ech_entry_t) + 511) / 512) + (ech_numblk * 8 + 511) / 512;
fs_len = ech_numblk*512;
fs_base = realloc(fs_base, fs_len);
if(!fs_base) { fprintf(stderr,"mkbootimg: %s\r\n",lang[ERR_MEM]); exit(1); }
memset(fs_base, 0, fs_len);
/* superblock */
memcpy(fs_base + 4, "_ECH_FS_", 8);
memcpy(fs_base + 12, &ech_numblk, 8);
j = (ech_maxents * sizeof(ech_entry_t) + 511) / 512;
memcpy(fs_base + 20, &j, 8);
j = 512;
memcpy(fs_base + 28, &j, 8);
memcpy(fs_base + 40, &ech_uuid, 16);
/* allocation table */
for(i = 0, ptr = (uint64_t*)(fs_base + 16 * 512); i < offs; i++, ptr++)
*ptr = UINT64_C(0xfffffffffffffff0);
/* directory entries */
ent = (ech_entry_t*)(fs_base + (16 + (ech_numblk * 8 + 511) / 512) * 512);
for(i = 0; (int)i < ech_numents; i++, ent++) {
memcpy(ent, &ech_ents[i], sizeof(ech_entry_t));
if(!ent->type) {
if(!ent->size)
ent->payload = UINT64_C(0xffffffffffffffff);
else {
ent->payload += offs;
j = ent->payload + 1;
while(ech_ents[i].size > 512) {
ech_ents[i].size -= 512;
*ptr++ = j++;
}
*ptr++ = UINT64_C(0xffffffffffffffff);
}
}
}
/* file data */
if(ech_data && ech_size)
memcpy(fs_base + offs * 512, ech_data, ech_size);
/* free resources */
if(ech_ents) { free(ech_ents); ech_ents = NULL; }
ech_numents = 0;
ech_maxents = 0;
if(ech_data) { free(ech_data); ech_data = NULL; }
ech_size = 0;
ech_numblk = 0;
}

View file

@ -40,6 +40,10 @@ void fsz_open(gpt_t *gpt_entry);
void fsz_add(struct stat *st, char *name, unsigned char *content, int size);
void fsz_close();
void ech_open(gpt_t *gpt_entry);
void ech_add(struct stat *st, char *name, unsigned char *content, int size);
void ech_close();
void jamesm_open(gpt_t *gpt_entry);
void jamesm_add(struct stat *st, char *name, unsigned char *content, int size);
void jamesm_close();
@ -50,6 +54,7 @@ fsdrv_t fsdrv[] = {
{ "cpio", {0}, cpio_open, cpio_add, cpio_close },
{ "tar", { 0x65706154, 0x4120, 0x6372, { 0x68,0x69,0x76,0x65,0x20,0x46,0x53,0x20} }, tar_open, tar_add, tar_close },
{ "FS/Z", { 0x5A2F534F, 0x0000, 0x5346, { 0x2F,0x5A,0x00,0x00,0x00,0x00,0x00,0x00} }, fsz_open, fsz_add, fsz_close },
{ "echfs", { 0x66686365, 0x6973, 0x7673, { 0x65,0x72,0x79,0x6C,0x61,0x6D,0x65,0x00} }, ech_open, ech_add, ech_close },
{ "OS/Z usr (x86_64)", { 0x5A2F534F, 0x8664, 0x5346, { 0x2F,0x5A,0x00,0x00,0x75,0x73,0x72,0x00} }, NULL, NULL, NULL },
{ "OS/Z usr (AArch64)", { 0x5A2F534F, 0xAA64, 0x5346, { 0x2F,0x5A,0x00,0x00,0x75,0x73,0x72,0x00} }, NULL, NULL, NULL },
{ "OS/Z var", { 0x5A2F534F, 0x0000, 0x5346, { 0x2F,0x5A,0x00,0x00,0x76,0x61,0x72,0x00} }, NULL, NULL, NULL },

View file

@ -382,12 +382,12 @@ typedef struct {
* Meta labels *
*********************************************************/
/* meta labels are list of sector aligned, zero terminated JSON strings,
/* meta labels are list of sector aligned, key value pairs (with possibly binary values),
* filled up with zeros to be multiple of sector size.
*
* Example (assuming meta label file starts at lsn 1234):
* {"icon":"/usr/firefox/share/icon.png"} (zeros padding to sector size)
* {"icon":"/usr/vlc/share/icon.svg","downloaded":"http://videolan.org"} (zeros, at least one)
* (length) "icon" (zero) "/usr/firefox/share/icon.png" (zero) (zeros padding to sector size)
* (length) "icon" (zero) "/usr/vlc/share/icon.svg" (zeros padding to sector size)
*
* Inode of /usr/firefox/bin/firefox: metalabel=1234
* Inode of /usr/vlc/bin/vlc: metalabel=1235
@ -396,7 +396,7 @@ typedef struct {
* must be careful to allocate contiguous sectors for a meta block. This complicates things
* a bit when large meta label blocks (>4096) are written, but simplifies a lot on read by
* eliminating the need of translating LSNs for meta labels file. As meta labels are read more
* often than written, and usually one JSON is smaller than 4096, this is intentional.
* often than written, and usually one meta is smaller than 4096, this is intentional.
* In other words, meta label blocks are one or more contiguous sectors per inode on disk, and
* meta labels file covers them just like bad sectors file covers bad sectors.
*/

View file

@ -38,6 +38,7 @@ fsdrivers:
dw tar_initrd
dw sfs_initrd
dw jamesm_initrd
dw ech_initrd
dw 0
; ----------- FS/Z ----------
@ -654,3 +655,59 @@ jamesm_initrd:
add esi, ebx
ret
.ks: dd 0
; ----------- echfs ----------
; Find the kernel on initrd
; IN: esi: initrd pointer, ecx: initrd end, edi: kernel filename
; OUT: On Success
; esi: pointer to the first byte, ecx: size in bytes
; On Error
; ecx: 0
ech_initrd:
cmp dword [esi + 4], '_ECH'
jne .err
cmp dword [esi + 8], '_FS_'
jne .err
mov edx, esi
mov esi, dword[esi + 12]
shl esi, 3
add esi, 16*512
mov ebx, 0FFFFFFFFh
.again: xor ecx, ecx
@@: inc cx
cmp byte [edi + ecx], 0
jz @f
cmp byte [edi + ecx], '/'
jne @b
@@:
.next: cmp dword [esi], 0
jz .err
cmp dword [esi], ebx
jne .not
cmp byte [esi + ecx + 9], 0
jnz .not
push esi
push edi
push ecx
add esi, 9
rep cmpsb
pop ecx
pop edi
pop esi
jnz .not
mov ebx, dword [esi + 240]
add edi, ecx
inc edi
cmp byte [edi - 1], '/'
je .again
cmp byte [esi + 8], 0
jnz .err
mov ecx, dword [esi + 248]
mov esi, ebx
shl esi, 9
add esi, edx
ret
.not: add esi, 256
jmp .next
.err: xor ecx, ecx
ret

View file

@ -277,6 +277,40 @@ file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
return ret;
}
/**
* EchFS
* http://github.com/echfs/echfs
*/
file_t ech_initrd(unsigned char *initrd_p, char *kernel)
{
uint64_t parent = 0xffffffffffffffffUL, n;
unsigned char *ptr;
char *end, *fn;
int k = 0;
file_t ret = { NULL, 0 };
if(initrd_p==NULL || kernel==NULL || memcmp(initrd_p+4,"_ECH_FS_",8))
return ret;
DBG(" * EchFS %s\n",kernel);
memcpy(&k, initrd_p + 28, 4);
memcpy(&n, initrd_p + 12, 8);
ptr = initrd_p + (((n * 8 + k - 1) / k) + 16) * k;
for(end = fn = kernel; *end && *end != '/'; end++);
while(*((uint64_t*)ptr)) {
if(*((uint64_t*)ptr) == parent && !memcmp(ptr + 9, fn, end - fn) && !ptr[9 + end - fn]) {
parent = *((uint64_t*)(ptr + 240));
if(!*end) {
ret.size=*((uint64_t*)(ptr + 248));
ret.ptr=(uint8_t*)(initrd_p + parent * k);
break;
}
end++;
for(fn = end; *end && *end != '/'; end++);
}
ptr += 256;
}
return ret;
}
/**
* Static file system drivers registry
*/
@ -286,5 +320,6 @@ file_t (*fsdrivers[]) (unsigned char *, char *) = {
tar_initrd,
sfs_initrd,
jamesm_initrd,
ech_initrd,
NULL
};

View file

@ -280,6 +280,40 @@ file_t jamesm_initrd(unsigned char *initrd_p, char *kernel)
return ret;
}
/**
* EchFS
* http://github.com/echfs/echfs
*/
file_t ech_initrd(unsigned char *initrd_p, char *kernel)
{
UINT64 parent = 0xffffffffffffffffUL, n;
unsigned char *ptr;
char *end, *fn;
int k = 0;
file_t ret = { NULL, 0 };
if(initrd_p==NULL || kernel==NULL || CompareMem(initrd_p+4,"_ECH_FS_",8))
return ret;
DBG(L" * EchFS %s\n",a2u(kernel));
memcpy(&k, initrd_p + 28, 4);
memcpy(&n, initrd_p + 12, 8);
ptr = initrd_p + (((n * 8 + k - 1) / k) + 16) * k;
for(end = fn = kernel; *end && *end != '/'; end++);
while(*((UINT64*)ptr)) {
if(*((UINT64*)ptr) == parent && !CompareMem(ptr + 9, fn, end - fn) && !ptr[9 + end - fn]) {
parent = *((UINT64*)(ptr + 240));
if(!*end) {
ret.size=*((UINTN*)(ptr + 248));
ret.ptr=(UINT8*)(initrd_p + parent * k);
break;
}
end++;
for(fn = end; *end && *end != '/'; end++);
}
ptr += 256;
}
return ret;
}
/**
* Static file system drivers registry
*/
@ -289,5 +323,6 @@ file_t (*fsdrivers[]) (unsigned char *, char *) = {
tar_initrd,
sfs_initrd,
jamesm_initrd,
ech_initrd,
NULL
};