]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/build.pl
update
[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 $output_dir    = $ENV{OUTPUT_DIR}    || '.';
32 my $make_inc_file = $ENV{MAKE_INC_FILE} || "mod.make.inc";
33
34 my $flags_cc     = "";
35 $flags_cc = "-m32" if $arch eq 'x86';
36 $flags_cc = "-m64" if $arch eq 'amd64';
37
38
39 my $modulesfile      = $ARGV[1];
40 my $entryname        = $ARGV[2];
41
42 sub usage()
43 {
44   print STDERR "$0 modulefile entry\n";
45 }
46
47 # Write a string to a file, overwriting it.
48 # 1:    filename
49 # 2..n: Strings to write to the file
50 sub write_to_file
51 {
52   my $file = shift;
53
54   open(A, ">$file") || die "Cannot open $file!";
55   while ($_ = shift) {
56     print A;
57   }
58   close A;
59 }
60
61 sub first_word($)
62 {
63   (split /\s+/, shift)[0]
64 }
65
66 # build object files from the modules
67 sub build_obj($$$)
68 {
69   my ($cmdline, $modname, $no_strip) = @_;
70   my $_file = first_word($cmdline);
71
72   my $file = L4::ModList::search_file($_file, $module_path)
73     || die "Cannot find file $_file! Used search path: $module_path";
74
75   printf STDERR "Merging image %s to %s [%dkB]\n",
76                 $file, $modname, ((-s $file) + 1023) / 1024;
77   # make sure that the file isn't already compressed
78   system("$prog_gzip -dc $file > $modname.ugz 2> /dev/null");
79   $file = "$modname.ugz" if !$?;
80   system("$prog_objcopy -S $file $modname.obj 2> /dev/null")
81     if $strip && !$no_strip;
82   system("$prog_cp         $file $modname.obj")
83     if $? || !$strip || $no_strip;
84   my $uncompressed_size = -s "$modname.obj";
85
86   my $c_unc = Digest::MD5->new;
87   open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
88   $c_unc->addfile(*M);
89   close M;
90
91   system("$prog_gzip -9f $modname.obj && mv $modname.obj.gz $modname.obj")
92     if $compress;
93
94   my $c_compr = Digest::MD5->new;
95   open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
96   $c_compr->addfile(*M);
97   close M;
98
99   write_to_file("$modname.extra.s",
100       ".section .rodata.module_info               \n",
101       ".align 4                                   \n",
102       "_bin_${modname}_name:                      \n",
103       ".ascii \"$_file\"; .byte 0                 \n",
104       ".align 4                                   \n",
105       "_bin_${modname}_md5sum_compr:              \n",
106       ".ascii \"".$c_compr->hexdigest."\"; .byte 0\n",
107       ".align 4                                   \n",
108       "_bin_${modname}_md5sum_uncompr:            \n",
109       ".ascii \"".$c_unc->hexdigest."\"; .byte 0  \n",
110       ".align 4                                   \n",
111       ".section .module_info                      \n",
112       ".long _binary_${modname}_start             \n",
113       ".long ", (-s "$modname.obj"), "            \n",
114       ".long $uncompressed_size                   \n",
115       ".long _bin_${modname}_name                 \n",
116       ".long _bin_${modname}_md5sum_compr         \n",
117       ".long _bin_${modname}_md5sum_uncompr       \n",
118       ($arch eq 'x86' || $arch eq 'amd64' || $arch eq 'ppc32'
119        ? #".section .module_data, \"a\", \@progbits   \n" # Not Xen
120          ".section .module_data, \"awx\", \@progbits   \n" # Xen
121        : ".section .module_data, #alloc           \n"),
122       ".p2align 12                                \n",
123       ".global _binary_${modname}_start           \n",
124       ".global _binary_${modname}_end             \n",
125       "_binary_${modname}_start:                  \n",
126       ".incbin \"$modname.obj\"                   \n",
127       "_binary_${modname}_end:                    \n",
128       );
129   system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.s");
130   unlink("$modname.extra.s", "$modname.obj", "$modname.ugz");
131 }
132
133 sub build_mbi_modules_obj($@)
134 {
135   my $cmdline = shift;
136   my @mods = @_;
137   my $asm_string;
138
139   # generate mbi module structures
140   $asm_string .= ".align 4                         \n".
141                  ".section .data.modules_mbi       \n".
142                  ".global _modules_mbi_start;      \n".
143                  "_modules_mbi_start:              \n";
144
145   for (my $i = 0; $i < @mods; $i++) {
146     $asm_string .= ".long 0                        \n".
147                    ".long 0                        \n".
148                    ".long _modules_mbi_cmdline_$i  \n".
149                    ".long 0                        \n";
150   }
151
152   $asm_string .= ".global _modules_mbi_end;        \n".
153                  "_modules_mbi_end:                \n";
154
155   $asm_string .= ".section .data.cmdlines          \n";
156
157   # generate cmdlines
158   for (my $i = 0; $i < @mods; $i++) {
159     $asm_string .= "_modules_mbi_cmdline_$i:                  \n".
160                    ".ascii \"$mods[$i]->{cmdline}\"; .byte 0; \n";
161   }
162
163   $asm_string .= ".global _mbi_cmdline          \n".
164                  "_mbi_cmdline:                 \n".
165                  ".ascii \"$cmdline\"; .byte 0; \n";
166
167   write_to_file("mbi_modules.s", $asm_string);
168   system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.s");
169   unlink("mbi_modules.s");
170
171 }
172
173 sub build_objects(@)
174 {
175   my %entry = @_;
176   my @mods = @{$entry{mods}};
177   my $objs = "$output_dir/mbi_modules.bin";
178   
179   unlink($make_inc_file);
180
181   # generate module-names
182   for (my $i = 0; $i < @mods; $i++) {
183     $mods[$i]->{modname} = sprintf "mod%02d", $i;
184   }
185
186   build_mbi_modules_obj($entry{bootstrap}{cmdline}, @mods);
187
188   for (my $i = 0; $i < @mods; $i++) {
189     build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname},
190               $mods[$i]->{type} =~ /.+-nostrip$/);
191     $objs .= " $output_dir/$mods[$i]->{modname}.bin";
192   }
193
194   my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n";
195   $make_inc_str   .= "MOD_ADDR            := $entry{modaddr}"
196     if defined $entry{modaddr};
197
198   write_to_file($make_inc_file, $make_inc_str);
199 }
200
201
202 sub list_files(@)
203 {
204   my %entry = @_;
205   print join(' ', map { L4::ModList::search_file_or_die(first_word($_->{cmdline}),
206                                                                    $module_path) }
207                       @{$entry{mods}}), "\n";
208 }
209
210 sub dump_entry(@)
211 {
212   my %entry = @_;
213   print "modaddr=$entry{modaddr}\n";
214   print "$entry{bootstrap}{command}\n";
215   print "$entry{bootstrap}{cmdline}\n";
216   print join("\n", map { $_->{cmdline} } @{$entry{mods}}), "\n";
217   print join(' ', map { $_ } @{$entry{files}}), "\n";
218 }
219
220 # ------------------------------------------------------------------------
221
222 if (!$ARGV[2]) {
223   print STDERR "Error: Invalid usage!\n";
224   usage();
225   exit 1;
226 }
227
228 if (defined $output_dir)
229   {
230     if (not -d $output_dir)
231       {
232         mkdir $output_dir || die "Cannot create '$output_dir': $!";
233       }
234     chdir $output_dir || die "Cannot change to directory '$output_dir': $!";
235   }
236
237 my %entry = L4::ModList::get_module_entry($modulesfile, $entryname);
238
239 if ($ARGV[0] eq 'build')
240   {
241     build_objects(%entry);
242   }
243 elsif ($ARGV[0] eq 'list')
244   {
245     list_files(%entry);
246   }
247 elsif ($ARGV[0] eq 'dump')
248   {
249     dump_entry(%entry);
250   }