Skip to content

Commit 69ef0b7

Browse files
committed
added a script for building initramfs images
1 parent c53e45b commit 69ef0b7

3 files changed

Lines changed: 132 additions & 1 deletion

File tree

scripts/create_initramfs.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
# usage: ./create_initramfs.sh file1 file2 file3 ... -o outfile.img
4+
# input file names must be shorter then 255 chars
5+
# input files must be smaller then 4GiB
6+
# input files combined size must be smaller then 4GiB
7+
8+
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
9+
10+
if [ -z "$GIT_ROOT" ]; then
11+
echo "Not inside a Git repository."
12+
exit 1
13+
fi
14+
15+
python3 "$GIT_ROOT/scripts/internal/create_initramfs.py" "$@"
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import argparse
2+
import struct
3+
from pathlib import Path
4+
5+
6+
def parse():
7+
parser = argparse.ArgumentParser( description="Create initramfs with provided files")
8+
parser.add_argument("files", nargs="+", help="Files to add")
9+
parser.add_argument("-o", "--output", required=True, help="Output initramfs file")
10+
args = parser.parse_args()
11+
12+
files = [Path(f) for f in args.files]
13+
14+
missing = [f for f in files if not f.is_file()]
15+
if missing:
16+
print("These files are missing or not regular files:")
17+
for f in missing:
18+
print(" -", f)
19+
return
20+
21+
too_long = [f for f in files if len(f.name) > 255]
22+
if too_long:
23+
print("These files have too long names (max 255 chars):")
24+
for f in too_long:
25+
print(" -", f)
26+
return
27+
28+
oversized = [f for f in files if f.stat().st_size > 2**32 - 1]
29+
if oversized:
30+
print("These files have are too big (max 4GiB):")
31+
for f in oversized:
32+
print(" -", f)
33+
return
34+
35+
totalSize = 0
36+
for f in files:
37+
totalSize += f.stat().st_size
38+
if totalSize > 2**32 - 1:
39+
print(f"The total size of all files must be at most 4GiB ({ 2**32 - 1:,}) and is {totalSize:,}")
40+
41+
entries = [
42+
(path, open(path, "rb"))
43+
for path in files
44+
]
45+
outfile = open(args.output, "wb")
46+
47+
return entries, outfile
48+
49+
50+
def align2(x):
51+
return (x + 1) & ~1
52+
53+
54+
def align16(x):
55+
return (x + 15) & ~15
56+
57+
58+
def calcHeaderSize(entries):
59+
MAGIC_SIZE = 4
60+
VERSION_SIZE = 4
61+
FILE_COUNT_SIZE = 2
62+
out = MAGIC_SIZE + VERSION_SIZE + FILE_COUNT_SIZE
63+
for f, _ in entries:
64+
OFFSET_SIZE = 4
65+
SIZE_SIZE = 4
66+
NAME_LENGTH_SIZE = 1
67+
out += align2(OFFSET_SIZE + SIZE_SIZE + NAME_LENGTH_SIZE + len(f.name))
68+
return out
69+
70+
71+
def main():
72+
parsed = parse()
73+
if parsed is None:
74+
return
75+
76+
entries, outfile = parsed
77+
78+
headerSize = calcHeaderSize(entries)
79+
offset = align16(headerSize)
80+
81+
MAGIC = 0xB16B00B5
82+
VERSION = 0x00000000 # TODO:
83+
84+
outfile.write(struct.pack(">IIH", MAGIC, VERSION, len(entries)))
85+
86+
for path, file in entries:
87+
file_offset = offset
88+
file_size = path.stat().st_size
89+
file_name = path.name.encode()
90+
file_name_size = len(file_name)
91+
92+
fmt = f">IIB{file_name_size}s"
93+
94+
outfile.write(struct.pack(fmt, file_offset, file_size, file_name_size, file_name))
95+
96+
if (file_name_size + 1) % 2 == 1:
97+
outfile.write(b"\x00")
98+
99+
offset += align16(file_size)
100+
101+
for i in range((16 - headerSize % 16) % 16):
102+
outfile.write(b"\x00")
103+
104+
for path, file in entries:
105+
outfile.write(file.read())
106+
for i in range((16 - path.stat().st_size % 16) % 16):
107+
outfile.write(b"\x00")
108+
109+
file.close()
110+
111+
112+
if __name__ == "__main__":
113+
main()

src/kernel/hal/initramfs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "dt/dt.h"
44
#include "hal_internal.h"
55
#include "stdbigos/buffer.h"
6+
#include "stdbigos/math.h"
67
#include "stdbigos/string.h"
78

89
/*
@@ -12,7 +13,8 @@
1213
* u32 version
1314
* u16 - file_count
1415
*
15-
* u32 - offset (from the start of initramfs)
16+
* aligned to 16bit boundry relative to the start of initramfs
17+
* u32 - offset (from the start of initramfs)
1618
* u32 - size
1719
* u8 - namesize
1820
* char[] - name
@@ -79,6 +81,7 @@ static error_t find_file_by_name(const char* filename, buffer_t initramfs_buff,
7981
buffer_t target_filename_buff = make_buffer(filename, strlen(filename));
8082
buffer_t filename_buff = make_buffer(initramfs_buff.data + cursor, file_name_size);
8183
cursor += file_name_size;
84+
cursor = ALIGN_UP(cursor, sizeof(u16));
8285

8386
if (buffer_memcmp(target_filename_buff, filename_buff) == 0) {
8487
if (headerOUT->offset + headerOUT->size > initramfs_buff.size)

0 commit comments

Comments
 (0)