]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/build.pl
Inital import
[l4.git] / l4 / pkg / bootstrap / server / src / build.pl
1 #! /usr/bin/perl -W
2 #
3 # (c) 2008-2009 Technische Universität Dresden
4 # This file is part of TUD:OS and distributed under the terms of the
5 # GNU General Public License 2.
6 # Please see the COPYING-GPL-2 file for details.
7 #
8 # Adam Lackorzynski <adam@os.inf.tu-dresden.de>
9 #
10
11 use strict;
12
13 BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib'
14            if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';}
15
16 use Digest::MD5;
17 use L4::ModList;
18
19
20 my $cross_compile_prefix = $ENV{CROSS_COMPILE} || '';
21 my $arch                 = $ENV{OPT_ARCH}     || "x86";
22
23 my $module_path  = $ENV{SEARCHPATH}   || ".";
24 my $prog_objcopy = $ENV{OBJCOPY}      || "${cross_compile_prefix}objcopy";
25 my $prog_cc      = $ENV{CC}           || "${cross_compile_prefix}gcc";
26 my $prog_ld      = $ENV{LD}           || "${cross_compile_prefix}ld";
27 my $prog_cp      = $ENV{PROG_CP}      || "cp";
28 my $prog_gzip    = $ENV{PROG_GZIP}    || "gzip";
29 my $compress     = $ENV{OPT_COMPRESS} || 0;
30 my $strip        = $ENV{OPT_STRIP}    || 1;
31 my $flags_cc     = ($arch eq 'amd64' ? "-m64" : "");
32
33 my $make_inc_file = $ENV{MAKE_INC_FILE} || "mod.make.inc";
34
35 my $modulesfile      = $ARGV[0];
36 my $entryname        = $ARGV[1];
37
38 sub usage()
39 {
40   print STDERR "$0 modulefile entry\n";
41 }
42
43 # Write a string to a file, overwriting it.
44 # 1:    filename
45 # 2..n: Strings to write to the file
46 sub write_to_file
47 {
48   my $file = shift;
49
50   open(A, ">$file") || die "Cannot open $file!";
51   while ($_ = shift) {
52     print A;
53   }
54   close A;
55 }
56
57 sub first_word($)
58 {
59   (split /\s+/, shift)[0]
60 }
61
62 # build object files from the modules
63 sub build_obj($$$)
64 {
65   my ($cmdline, $modname, $no_strip) = @_;
66   my $_file = first_word($cmdline);
67
68   my $file = L4::ModList::search_file($_file, $module_path)
69     || die "Cannot find file $_file! Used search path: $module_path";
70
71   printf STDERR "Merging image %s to %s\n", $file, $modname;
72   # make sure that the file isn't already compressed
73   system("$prog_gzip -dc $file > $modname.ugz 2> /dev/null");
74   $file = "$modname.ugz" if !$?;
75   system("$prog_objcopy -S $file $modname.obj 2> /dev/null")
76     if $strip && !$no_strip;
77   system("$prog_cp         $file $modname.obj")
78     if $? || !$strip || $no_strip;
79   my $uncompressed_size = -s "$modname.obj";
80
81   my $c_unc = Digest::MD5->new;
82   open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
83   $c_unc->addfile(*M);
84   close M;
85
86   system("$prog_gzip -9f $modname.obj && mv $modname.obj.gz $modname.obj")
87     if $compress;
88
89   my $c_compr = Digest::MD5->new;
90   open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
91   $c_compr->addfile(*M);
92   close M;
93
94   write_to_file("$modname.extra.s",
95       ".section .rodata.module_info               \n",
96       ".align 4                                   \n",
97       "_bin_${modname}_name:                      \n",
98       ".ascii \"$_file\"; .byte 0                 \n",
99       ".align 4                                   \n",
100       "_bin_${modname}_md5sum_compr:              \n",
101       ".ascii \"".$c_compr->hexdigest."\"; .byte 0\n",
102       ".align 4                                   \n",
103       "_bin_${modname}_md5sum_uncompr:            \n",
104       ".ascii \"".$c_unc->hexdigest."\"; .byte 0  \n",
105       ".align 4                                   \n",
106       ".section .module_info                      \n",
107       ".long _binary_${modname}_start             \n",
108       ".long ", (-s "$modname.obj"), "            \n",
109       ".long $uncompressed_size                   \n",
110       ".long _bin_${modname}_name                 \n",
111       ".long _bin_${modname}_md5sum_compr         \n",
112       ".long _bin_${modname}_md5sum_uncompr       \n",
113       ($arch eq 'x86' || $arch eq 'amd64' || $arch eq 'ppc32'
114        ? #".section .module_data, \"a\", \@progbits   \n" # Not Xen
115          ".section .module_data, \"awx\", \@progbits   \n" # Xen
116        : ".section .module_data, #alloc           \n"),
117       ".p2align 12                                \n",
118       ".global _binary_${modname}_start           \n",
119       ".global _binary_${modname}_end             \n",
120       "_binary_${modname}_start:                  \n",
121       ".incbin \"$modname.obj\"                   \n",
122       "_binary_${modname}_end:                    \n",
123       );
124   system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.s");
125   unlink("$modname.extra.s", "$modname.obj", "$modname.ugz");
126 }
127
128 sub build_mbi_modules_obj(@)
129 {
130   my @mods = @_;
131   my $asm_string;
132
133   # generate mbi module structures
134   $asm_string .= ".align 4                         \n".
135                  ".section .data.modules_mbi       \n".
136                  ".global _modules_mbi_start;      \n".
137                  "_modules_mbi_start:              \n";
138
139   for (my $i = 0; $i < @mods; $i++) {
140     $asm_string .= ".long 0                        \n".
141                    ".long 0                        \n".
142                    ".long _modules_mbi_cmdline_$i  \n".
143                    ".long 0                        \n";
144   }
145
146   $asm_string .= ".global _modules_mbi_end;        \n".
147                  "_modules_mbi_end:                \n";
148
149   $asm_string .= ".section .data.cmdlines          \n";
150
151   # generate cmdlines
152   for (my $i = 0; $i < @mods; $i++) {
153     $asm_string .= "_modules_mbi_cmdline_$i:                  \n".
154                    ".ascii \"$mods[$i]->{cmdline}\"; .byte 0; \n";
155   }
156
157   write_to_file("mbi_modules.s", $asm_string);
158   system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.s");
159   unlink("mbi_modules.s");
160
161 }
162
163 sub build_objects(@)
164 {
165   my %entry = @_;
166   my @mods = @{$entry{mods}};
167   my $objs = "mbi_modules.bin";
168   
169   unlink($make_inc_file);
170
171   # generate module-names
172   for (my $i = 0; $i < @mods; $i++) {
173     $mods[$i]->{modname} = sprintf "mod%02d", $i;
174   }
175
176   build_mbi_modules_obj(@mods);
177
178   for (my $i = 0; $i < @mods; $i++) {
179     build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname},
180               $mods[$i]->{type} =~ /.+-nostrip$/);
181     $objs .= " $mods[$i]->{modname}.bin";
182   }
183
184   my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n";
185   $make_inc_str   .= "MOD_ADDR            := $entry{modaddr}"
186     if defined $entry{modaddr};
187
188   write_to_file($make_inc_file, $make_inc_str);
189 }
190
191 # ------------------------------------------------------------------------
192
193 if (!$ARGV[1]) {
194   print STDERR "Error: Invalid usage!\n";
195   usage();
196   exit 1;
197 }
198
199 my %entry = L4::ModList::get_module_entry($modulesfile, $entryname);
200 build_objects(%entry);
201