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.
8 # Adam Lackorzynski <adam@os.inf.tu-dresden.de>
13 BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib'
14 if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';}
20 my $cross_compile_prefix = $ENV{CROSS_COMPILE} || '';
21 my $arch = $ENV{OPT_ARCH} || "x86";
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";
35 $flags_cc = "-m32" if $arch eq 'x86';
36 $flags_cc = "-m64" if $arch eq 'amd64';
39 my $modulesfile = $ARGV[1];
40 my $entryname = $ARGV[2];
44 print STDERR "$0 modulefile entry\n";
47 # Write a string to a file, overwriting it.
49 # 2..n: Strings to write to the file
54 open(A, ">$file") || die "Cannot open $file!";
63 (split /\s+/, shift)[0]
66 # build object files from the modules
69 my ($cmdline, $modname, $no_strip) = @_;
70 my $_file = first_word($cmdline);
72 my $file = L4::ModList::search_file($_file, $module_path)
73 || die "Cannot find file $_file! Used search path: $module_path";
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";
86 my $c_unc = Digest::MD5->new;
87 open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
91 system("$prog_gzip -9f $modname.obj && mv $modname.obj.gz $modname.obj")
94 my $c_compr = Digest::MD5->new;
95 open(M, "$modname.obj") || die "Failed to open $modname.obj: $!";
96 $c_compr->addfile(*M);
99 my $size = -s "$modname.obj";
100 my $md5_compr = $c_compr->hexdigest;
101 my $md5_uncompr = $c_unc->hexdigest;
103 my $section_attr = ($arch eq 'x86' || $arch eq 'amd64' || $arch eq 'ppc32'
104 ? #'"a", @progbits' # Not Xen
105 '\"awx\", @progbits' # Xen
108 write_to_file("$modname.extra.c",qq|
112 unsigned size_uncompr;
115 char const *md5sum_compr;
116 char const *md5sum_uncompr;
117 } __attribute__((packed));
119 extern char const _binary_${modname}_start[];
121 struct Mi const _binary_${modname}_info
122 __attribute__((section(".module_info"), aligned(4))) =
124 _binary_${modname}_start, $size, $uncompressed_size,
125 "$_file", "$cmdline",
126 "$md5_compr", "$md5_uncompr"
129 asm (".section .module_data, $section_attr \\n"
131 ".global _binary_${modname}_start \\n"
132 "_binary_${modname}_start: \\n"
133 ".incbin \\"$modname.obj\\" \\n"
134 "_binary_${modname}_end: \\n");
137 system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.c");
138 unlink("$modname.extra.c", "$modname.obj", "$modname.ugz");
141 sub build_mbi_modules_obj($@)
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");
157 my @mods = @{$entry{mods}};
158 my $objs = "$output_dir/mbi_modules.bin";
160 unlink($make_inc_file);
162 # generate module-names
163 for (my $i = 0; $i < @mods; $i++) {
164 $mods[$i]->{modname} = sprintf "mod%02d", $i;
167 build_mbi_modules_obj($entry{bootstrap}{cmdline}, @mods);
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";
175 my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n";
176 $make_inc_str .= "MOD_ADDR := $entry{modaddr}"
177 if defined $entry{modaddr};
179 write_to_file($make_inc_file, $make_inc_str);
186 print join(' ', map { L4::ModList::search_file_or_die(first_word($_->{cmdline}),
188 @{$entry{mods}}), "\n";
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";
201 # ------------------------------------------------------------------------
204 print STDERR "Error: Invalid usage!\n";
209 if (defined $output_dir)
211 if (not -d $output_dir)
213 mkdir $output_dir || die "Cannot create '$output_dir': $!";
215 chdir $output_dir || die "Cannot change to directory '$output_dir': $!";
218 my %entry = L4::ModList::get_module_entry($modulesfile, $entryname);
220 if ($ARGV[0] eq 'build')
222 build_objects(%entry);
224 elsif ($ARGV[0] eq 'list')
228 elsif ($ARGV[0] eq 'dump')