Skip to content

Commit 3e2df71

Browse files
committed
classes: add k3-vendor-image
Signed-off-by: Trevor Gamblin <tgamblin@baylibre.com>
1 parent 1776b53 commit 3e2df71

1 file changed

Lines changed: 148 additions & 0 deletions

File tree

classes/k3-vendor-image.bbclass

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# K3 Image Common Functions
2+
# This file contains shared functions for K3 image recipes
3+
4+
# Create bootfs partition with kernel, env, Initramfs and dtbs
5+
# Layout matches the reference titan image (Bianbu-GNOME-K3)
6+
# Triggered before ext4 rootfs generation and WIC image generation
7+
do_image_ext4[prefuncs] += "do_create_bootfs"
8+
do_image_wic[prefuncs] += "do_create_bootfs"
9+
10+
python do_create_bootfs() {
11+
import subprocess, os, shutil
12+
13+
deploydir = d.getVar('DEPLOY_DIR_IMAGE')
14+
bootfs_dir = os.path.join(deploydir, 'bootfs')
15+
bootfs_img = os.path.join(deploydir, 'bootfs.ext4')
16+
machine = d.getVar('MACHINE')
17+
kver = d.getVar('K3_KERNEL_VERSION') or '6.18.3'
18+
kver_generic = f"{kver}-generic"
19+
20+
# 1. Reset and prepare bootfs directory
21+
bb.utils.remove(bootfs_dir, recurse=True)
22+
bb.utils.mkdirhier(bootfs_dir)
23+
24+
# DTB subdirectory: spacemit/<version>/
25+
dtb_subdir = os.path.join(bootfs_dir, 'spacemit', kver_generic)
26+
bb.utils.mkdirhier(dtb_subdir)
27+
28+
# Define helper function for copy logic
29+
def copy_file(src_name, dst_path):
30+
src = os.path.join(deploydir, src_name)
31+
if os.path.exists(src):
32+
shutil.copy2(src, dst_path)
33+
bb.note(f"Copied {src_name} to bootfs")
34+
return True
35+
else:
36+
bb.warn(f"File not found: {src_name}")
37+
return False
38+
39+
# 2. Copy kernel (compressed vmlinuz)
40+
vmlinuz_name = f"vmlinuz-{kver_generic}"
41+
if not copy_file(vmlinuz_name, os.path.join(bootfs_dir, vmlinuz_name)):
42+
# Fallback: compress Image on the fly
43+
image_path = os.path.join(deploydir, 'Image')
44+
if os.path.exists(image_path):
45+
import gzip
46+
dst = os.path.join(bootfs_dir, vmlinuz_name)
47+
with open(image_path, 'rb') as f_in:
48+
with gzip.open(dst, 'wb', compresslevel=9) as f_out:
49+
shutil.copyfileobj(f_in, f_out)
50+
bb.note(f"Compressed Image -> {vmlinuz_name}")
51+
else:
52+
bb.fatal("Neither vmlinuz nor Image found")
53+
54+
# 3. Initramfs (rename to initrd.img-<version>)
55+
initrd_name = f"initrd.img-{kver_generic}"
56+
initramfs = next((f for f in os.listdir(deploydir)
57+
if f.startswith('initramfs-image-') and f.endswith('.cpio.gz')), None)
58+
if initramfs:
59+
copy_file(initramfs, os.path.join(bootfs_dir, initrd_name))
60+
else:
61+
bb.fatal("initramfs not found")
62+
63+
# 4. System.map and config
64+
copy_file(f"System.map-{kver_generic}", os.path.join(bootfs_dir, f"System.map-{kver_generic}"))
65+
copy_file(f"config-{kver_generic}", os.path.join(bootfs_dir, f"config-{kver_generic}"))
66+
67+
# 5. DTBs -> spacemit/<version>/
68+
dtbs = [f for f in os.listdir(deploydir)
69+
if f.endswith('.dtb') and not os.path.islink(os.path.join(deploydir, f))]
70+
if not dtbs:
71+
bb.warn("No DTB files found")
72+
for dtb in dtbs:
73+
copy_file(dtb, os.path.join(dtb_subdir, dtb))
74+
75+
# 6. Boot logo (spacemit.bmp from u-boot recipe)
76+
copy_file('spacemit.bmp', os.path.join(bootfs_dir, 'bianbu.bmp'))
77+
78+
# 7. env_k3.txt (generate to match reference image format)
79+
env_content = f"""knl_name={vmlinuz_name}
80+
ramdisk_name={initrd_name}
81+
dtb_dir=spacemit/{kver_generic}
82+
ramdisk_addr=0x130000000
83+
loglevel=8
84+
commonargs=setenv bootargs plymouth.prefer-fbcon plymouth.ignore-serial-consoles splash
85+
"""
86+
env_path = os.path.join(bootfs_dir, 'env_k3.txt')
87+
with open(env_path, 'w') as f:
88+
f.write(env_content)
89+
bb.note("Generated env_k3.txt for titan bootfs")
90+
91+
# 8. Calculate size and generate image (add 15% margin)
92+
import math
93+
total_size_kb = sum(os.path.getsize(os.path.join(root, f))
94+
for root, dirs, files in os.walk(bootfs_dir)
95+
for f in files) / 1024
96+
calc_mb = math.ceil((total_size_kb * 1.15) / 1024) + 1
97+
final_mb = max(int(d.getVar('SDIMG_BOOTFS_SIZE') or 256), calc_mb)
98+
99+
# 9. Call mke2fs to create ext4 image
100+
# Disable orphan_file and metadata_csum_seed: U-Boot 2022.10 ext4 driver
101+
# does not recognize these features and fails to mount the filesystem.
102+
try:
103+
cmd = ['mke2fs', '-F', '-L', 'bootfs', '-t', 'ext4',
104+
'-b', '4096',
105+
'-O', '^orphan_file,^metadata_csum_seed',
106+
'-d', bootfs_dir, bootfs_img, f'{final_mb}M']
107+
subprocess.run(cmd, check=True, capture_output=True, text=True)
108+
bb.note(f"bootfs.ext4 ({final_mb}MB) created successfully")
109+
except subprocess.CalledProcessError as e:
110+
bb.fatal(f"mke2fs failed: {e.stderr}")
111+
}
112+
113+
# Inject bootinfo into WIC image after WIC generation
114+
do_image_wic[postfuncs] += "write_bootinfo_to_wic"
115+
116+
python write_bootinfo_to_wic() {
117+
import subprocess
118+
import os
119+
120+
# 1. Retrieve Yocto path variables
121+
imgdeploydir = d.getVar('IMGDEPLOYDIR')
122+
image_name = d.getVar('IMAGE_NAME')
123+
deploy_dir = d.getVar('DEPLOY_DIR_IMAGE')
124+
125+
# K3 uses bootinfo_block.bin (from u-boot-k3)
126+
bootinfo_path = os.path.join(deploy_dir, 'bootinfo_block.bin')
127+
128+
# Define the physical path of the generated .wic file
129+
wic_path = os.path.join(imgdeploydir, image_name + '.wic')
130+
131+
# 2. Safety checks
132+
if not os.path.exists(bootinfo_path):
133+
bb.warn(f"[Post-WIC] bootinfo file not found: {bootinfo_path} - skipping injection")
134+
return
135+
136+
if not os.path.exists(wic_path):
137+
bb.error(f"[Post-WIC] Target WIC file not found: {wic_path}")
138+
return
139+
140+
# 3. Perform the dd injection
141+
try:
142+
# Write bootinfo at 1M offset (128K size) - K3 specific
143+
cmd = ['dd', f'if={bootinfo_path}', f'of={wic_path}', 'bs=1K', 'seek=1024', 'count=128', 'conv=notrunc']
144+
subprocess.run(cmd, check=True, capture_output=True)
145+
bb.note(f"[Post-WIC] Successfully injected bootinfo (128K @ 1M) into {os.path.basename(wic_path)}")
146+
except subprocess.CalledProcessError as e:
147+
bb.error(f"[Post-WIC] dd command failed: {e.stderr.decode()}")
148+
}

0 commit comments

Comments
 (0)