11#!/usr/bin/python3 -I
2+ import argparse
23import os
34import subprocess
45import sys
56import re
67from typing import List , Tuple
78
9+ class SectionAdder :
10+ def __init__ (self , base_addr , round_to_next ):
11+ self ._address = base_addr
12+ self ._args = []
13+ self .round_to_next = round_to_next
14+ def add_section (self , section_name , path ):
15+ self ._address = self .round_to_next (self ._address )
16+ self ._args .append (f"--add-section=.{ section_name } ={ path } " )
17+ self ._args .append (f"--change-section-vma=.{ section_name } ={ self ._address } " )
18+ self ._address += os .stat (path ).st_size
19+ def objcopy_args (self ):
20+ return self ._args
21+
822def main (args ):
923 section_re = re .compile (rb"\A *(?:0|[1-9][0-9]*) +([!-~]+) +([0-9a-f]{8}) +([0-9a-f]{16}) +[0-9a-f]{16} +[0-9a-f]{8} +2" )
1024 alignment_mask = (1 << 21 ) - 1
11- if len (args ) != 6 :
12- print (f"Usage: uki-generate HYPERVISOR CONFIG KERNEL INITRAMFS OUTPUT" , file = sys .stderr )
13- sys .exit (1 )
14- _ , hyp , cfg , kern , initramfs , out = args
25+ parser = argparse .ArgumentParser (
26+ prog = 'uki-generate' ,
27+ description = 'Create a unified kernel image for Qubes OS' )
28+ parser .add_argument ('hypervisor' , help = "Xen Kernel" )
29+ parser .add_argument ('config' , help = "Xen config file" )
30+ parser .add_argument ('kernel' , help = "Dom0 kernel" )
31+ parser .add_argument ('initramfs' )
32+ parser .add_argument ('output' , help = "UKI image save path" )
33+ parser .add_argument ('--custom-section' , nargs = 2 , action = 'append' , help = 'A custom section placed right before the kernel' )
34+ args = parser .parse_args (args [1 :])
35+ hyp , cfg , kern , initramfs , custom , out = args .hypervisor , args .config , args .kernel , args .initramfs , args .custom_section , args .output
1536 if hyp [0 ] != '/' :
1637 hyp = './' + hyp
1738 if out [0 ] != '/' :
@@ -38,27 +59,30 @@ def main(args):
3859 print (f"Fatal error: Address overflow: { f } exceeds { max_address } " , file = sys .stderr )
3960 sys .exit (1 )
4061 return (f + alignment_mask ) & ~ alignment_mask
41- base_address = round_to_next (max_vma )
42- kernel_vma = round_to_next (base_address + os .stat (cfg ).st_size )
43- initramfs_vma = round_to_next (kernel_vma + os .stat (kern ).st_size )
44- cmdline = [
45- "objcopy" ,
46- f"--section-alignment={ alignment_mask + 1 } " ,
47- f"--file-alignment={ 1 << 5 } " ,
48- #"--remove-section=.buildid",
49- "--remove-section=.annobin.*" ,
50- #"--strip-debug",
51- f"--add-section=.config={ cfg } " ,
52- f"--change-section-vma=.config={ base_address } " ,
53- f"--add-section=.kernel={ kern } " ,
54- f"--change-section-vma=.kernel={ kernel_vma } " ,
55- f"--add-section=.ramdisk={ initramfs } " ,
56- f"--change-section-vma=.ramdisk={ initramfs_vma } " ,
57- "--long-section-names=disable" ,
58- "--" ,
59- hyp ,
60- out ,
61- ]
62+
63+ adder = SectionAdder (base_addr = max_vma , round_to_next = round_to_next )
64+ adder .add_section ("config" , cfg )
65+ for (section , path ) in custom or []:
66+ adder .add_section (section , path )
67+ adder .add_section ("kernel" , kern )
68+ adder .add_section ("ramdisk" , initramfs )
69+ cmdline = (
70+ [
71+ "objcopy" ,
72+ f"--section-alignment={ alignment_mask + 1 } " ,
73+ f"--file-alignment={ 1 << 5 } " ,
74+ #"--remove-section=.buildid",
75+ "--remove-section=.annobin.*" ,
76+ #"--strip-debug",
77+ ]
78+ + adder .objcopy_args ()
79+ + [
80+ "--long-section-names=disable" ,
81+ "--" ,
82+ hyp ,
83+ out ,
84+ ]
85+ )
6286 subprocess .check_call (cmdline , stdin = subprocess .DEVNULL , stdout = subprocess .DEVNULL )
6387if __name__ == '__main__' :
6488 try :
0 commit comments