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