]> 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   my $size = -s "$modname.obj";
100   my $md5_compr = $c_compr->hexdigest;
101   my $md5_uncompr = $c_unc->hexdigest;
102
103   my $section_attr = ($arch eq 'x86' || $arch eq 'amd64' || $arch eq 'ppc32'
104        ? #'"a", @progbits' # Not Xen
105          '\"awx\", @progbits' # Xen
106        : '#alloc' );
107
108   write_to_file("$modname.extra.c",qq|
109     struct Mi {
110       void const *start;
111       unsigned size;
112       unsigned size_uncompr;
113       char const *name;
114       char const *cmdline;
115       char const *md5sum_compr;
116       char const *md5sum_uncompr;
117     } __attribute__((packed));
118
119     extern char const _binary_${modname}_start[];
120
121     struct Mi const _binary_${modname}_info
122     __attribute__((section(".module_info"), aligned(4))) =
123     {
124       _binary_${modname}_start, $size, $uncompressed_size,
125       "$_file", "$cmdline",
126       "$md5_compr", "$md5_uncompr"
127     };
128
129     asm (".section .module_data, $section_attr           \\n"
130          ".p2align 12                                    \\n"
131          ".global _binary_${modname}_start               \\n"
132          "_binary_${modname}_start:                      \\n"
133          ".incbin \\"$modname.obj\\"                     \\n"
134          "_binary_${modname}_end:                        \\n");
135   |);
136
137   system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.c");
138   unlink("$modname.extra.c", "$modname.obj", "$modname.ugz");
139 }
140
141 sub build_mbi_modules_obj($@)
142 {
143   my $cmdline = shift;
144   my @mods = @_;
145   my $asm_string;
146
147   # generate mbi module structures
148   write_to_file("mbi_modules.c", qq|char const _mbi_cmdline[] = "$cmdline";|);
149   system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.c");
150   unlink("mbi_modules.c");
151
152 }
153
154 sub build_objects(@)
155 {
156   my %entry = @_;
157   my @mods = @{$entry{mods}};
158   my $objs = "$output_dir/mbi_modules.bin";
159   
160   unlink($make_inc_file);
161
162   # generate module-names
163   for (my $i = 0; $i < @mods; $i++) {
164     $mods[$i]->{modname} = sprintf "mod%02d", $i;
165   }
166
167   build_mbi_modules_obj($entry{bootstrap}{cmdline}, @mods);
168
169   for (my $i = 0; $i < @mods; $i++) {
170     build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname},
171               $mods[$i]->{type} =~ /.+-nostrip$/);
172     $objs .= " $output_dir/$mods[$i]->{modname}.bin";
173   }
174
175   my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n";
176   $make_inc_str   .= "MOD_ADDR            := $entry{modaddr}"
177     if defined $entry{modaddr};
178
179   write_to_file($make_inc_file, $make_inc_str);
180 }
181
182
183 sub list_files(@)
184 {
185   my %entry = @_;
186   print join(' ', map { L4::ModList::search_file_or_die(first_word($_->{cmdline}),
187                                                                    $module_path) }
188                       @{$entry{mods}}), "\n";
189 }
190
191 sub dump_entry(@)
192 {
193   my %entry = @_;
194   print "modaddr=$entry{modaddr}\n";
195   print "$entry{bootstrap}{command}\n";
196   print "$entry{bootstrap}{cmdline}\n";
197   print join("\n", map { $_->{cmdline} } @{$entry{mods}}), "\n";
198   print join(' ', map { $_ } @{$entry{files}}), "\n";
199 }
200
201 # ------------------------------------------------------------------------
202
203 if (!$ARGV[2]) {
204   print STDERR "Error: Invalid usage!\n";
205   usage();
206   exit 1;
207 }
208
209 if (defined $output_dir)
210   {
211     if (not -d $output_dir)
212       {
213         mkdir $output_dir || die "Cannot create '$output_dir': $!";
214       }
215     chdir $output_dir || die "Cannot change to directory '$output_dir': $!";
216   }
217
218 my %entry = L4::ModList::get_module_entry($modulesfile, $entryname);
219
220 if ($ARGV[0] eq 'build')
221   {
222     build_objects(%entry);
223   }
224 elsif ($ARGV[0] eq 'list')
225   {
226     list_files(%entry);
227   }
228 elsif ($ARGV[0] eq 'dump')
229   {
230     dump_entry(%entry);
231   }