⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mknbi.pl

📁 linux下从网卡远程启动
💻 PL
📖 第 1 页 / 共 3 页
字号:
#!/usr/bin/perl -w# Program to create a netboot image for ROM/FreeDOS/DOS/Linux# Placed under GNU Public License by Ken Yap, December 2000# 2003.04.28 R. Main#  Tweaks to work with new first-dos.S for large disk imagesBEGIN {	push(@INC, '@@LIBDIR@@');}use strict;use Getopt::Long;use IO::Seekable;use Socket;use TruncFD;use Nbi;use Elf;use constant;use constant DEBUG => 0;use constant LUA_VERSION => 0x04000100;	# 4.0.1.0use bytes;use vars qw($libdir $version $format $target $output $module $relocseg $relocsegstr	$progreturns $param $append $rootdir $rootmode $ip $ramdisk $rdbase	$simhd $dishd $squashfd $first32 $showversion);sub check_file{	my ($f, $status);	$status = 1;	foreach $f (@_) {		if (!-e $f) {			print STDERR "$f: file not found\n";			$status = 0;		} elsif (!-f $f) {			print STDERR "$f: not a plain file\n";			$status = 0;		} elsif (!-r $f) {			print STDERR "$f: file not readable\n";			$status = 0;		}	}	return ($status);}sub mknbi_rom ($){	my ($module) = @_;	my ($romdesc);	$#ARGV >= 0 or die "Usage: $0 romimage\n";	return unless check_file($ARGV[0]);	$module->add_header("mknbi-rom-$version", $relocseg + 0x3E0, 0x6000, 6);	$romdesc = { file => $ARGV[0],		segment => 0x6000,		maxlen => 0x10000,		id => 16,		end => 1 };	$module->add_segment($romdesc);	$module->dump_segments();	$module->copy_file($romdesc);}sub mkelf_img ($){	my ($module) = @_;	my ($romdesc);	$#ARGV >= 0 or die "Usage: $0 .img-file\n";	return unless check_file($ARGV[0]);	$module->add_pm_header("mkelf-img-$version", $relocseg + 0x3E0, 0x60000, 0);	$romdesc = { file => $ARGV[0],		segment => 0x6000,		maxlen => 0x10000,		id => 16,		end => 1 };	$module->add_segment($romdesc);	$module->dump_segments();	$module->copy_file($romdesc);}sub inet_aton_warn{	my ($ip);	print STDERR "Warning: $_[0] cannot be resolved to an IP address\n" unless defined($ip = inet_aton($_[0]));	return ($ip);}sub resolve_names{	my ($i);	my ($client, $server, $gateway, $netmask, $hostname) = split(/:/, $_[0], 5);	unless (defined($hostname)) {		print STDERR "$_[0]: invalid specification\n";		return ($_[0]);	}	$client = inet_ntoa($i) if defined($i = &inet_aton_warn($client));	$server = inet_ntoa($i) if defined($i = &inet_aton_warn($server));	$gateway = inet_ntoa($i) if defined($i = &inet_aton_warn($gateway));	return (join(':', $client, $server, $gateway, $netmask, $hostname));}sub make_paramstring ($){	my ($paramsize) = @_;	my ($string, $nfsroot);	# --param= overrides everything	return ($param) if (defined($param));	# String substitute various options, should do sanity checks also	if (!defined($rootdir)) {		$rootdir = '/dev/nfs';	} elsif ($rootdir !~ m(^/dev/)) {		$nfsroot = $rootdir;		undef($nfsroot) if ($nfsroot eq 'kernel');		$rootdir = '/dev/nfs';	}	if (defined($ip)) {		if ($ip eq 'kernel') {			undef($ip);		} elsif ($ip !~ /^(rom|off|none|on|any|dhcp|bootp|rarp|both)$/) {			$ip = &resolve_names($ip);		}	} elsif (!defined($ramdisk)) {		print STDERR "Warning: The --ip option was not used; you may need it if you use NFSroot.\n\tPlease see the documentation.\n";	}	die "Ramdisk mode should be one of: top asis 0xNNNNNNNN (hex address)\n"		if (defined($rdbase) and $rdbase !~ /^(top|asis|0x[\da-fA-F]{1,8})$/);	# If rootmode is set, then check if it's rw or ro, and if so, use it	if (defined($rootmode) and $rootmode !~ /^(rw|ro)$/) {		die "-rootmode should be either rw or ro\n";		undef($rootmode);	}	$string = defined($rootmode) ? $rootmode : 'rw';	$string .= " root=$rootdir";	$string .= " nfsroot=$nfsroot" if (defined($nfsroot));	$string .= " ip=$ip" if (defined($ip));	$string .= " rdbase=$rdbase" if (defined($rdbase));	$string .= " $append" if (defined($append));	return ($string);}use constant HEADER_SEG_OFFSET => 0x220;	# in units of 16 bytesuse constant START_OFFSET => 0x280;		# in units of 16 bytesuse constant START_MAX_LENGTH => 6144;use constant PARAM_SEG_OFFSET => 0x240;		# in units of 16 bytesuse constant PARAM_MAX_LENGTH => 1024;sub mknbi_linux ($){	my ($module) = @_;	my ($startaddr, $setupfile, $setupfile32, $libfile, $kernelfile, $setupdesc);	my ($paramseg, $paramstring, $bootseg, $block);	my ($setupseg, $kernelseg, $kernellen, $ramdiskseg, $rdloc);	my ($setupsects, $flags, $syssize, $swapdev,		$ramsize, $vidmode, $rootdev, $sig, $ver, $bigker);	$startaddr = sprintf("%#x", ($relocseg + START_OFFSET) * 0x10);	$libfile = ($format eq 'elf') ? "first32elf\@${startaddr}.linux" : "first32\@${startaddr}.linux";	# if empty, use default	$setupfile = $first32 eq '' ? "$libdir/$libfile" : $first32;	$#ARGV >= 0 or die "Usage: $0 kernelimage [ramdisk]\n";	$kernelfile = $ARGV[0];	return unless check_file($setupfile, $kernelfile);	if (defined($ramdisk = $ARGV[1])) {		return unless check_file($ramdisk);	}	$module->add_pm_header("mknbi-linux-$version", $relocseg + HEADER_SEG_OFFSET, hex($startaddr), $progreturns);	$setupdesc = { file => $setupfile,		segment => hex($startaddr) / 0x10,		maxlen => START_MAX_LENGTH,		id => 16 };	$paramstring = &make_paramstring(PARAM_MAX_LENGTH);	$paramseg = { string => $paramstring,		segment => $relocseg + PARAM_SEG_OFFSET,		maxlen => 2048,		id => 17 };	$bootseg = { file => $kernelfile,		segment => $relocseg + 0x0,		len => 512,		maxlen => 512,		id => 18 };	$module->peek_file($bootseg, \$block, 512) == 512		or die "Error reading boot sector of $kernelfile\n";	(undef, $setupsects, $flags, $syssize, $swapdev, $ramsize, $vidmode,		$rootdev, $sig) = unpack('a497Cv7', $block);	if ($sig != 0xAA55) {		print STDERR "$kernelfile: not a Linux kernel image\n";		return;	}	print STDERR 'setupsects flags syssize swapdev ramsize vidmode rootdev sig', "\n" if (DEBUG);	print STDERR "$setupsects $flags $syssize $swapdev $ramsize $vidmode $rootdev $sig\n" if (DEBUG);	$setupseg = { file => $kernelfile,		segment => $relocseg + 0x20,		fromoff => 512,		len => $setupsects * 512,		maxlen => 8192,		id => 19 };	$module->peek_file($setupseg, \$block, 512) == 512		or die "Error reading first setup sector of $kernelfile\n";	(undef, $sig, $ver, undef, undef, undef, undef, undef, $flags) =		unpack('va4v5C2', $block);	print STDERR 'sig ver flags', "\n" if (DEBUG);	print STDERR "$sig $ver $flags\n" if (DEBUG);	if ($sig ne 'HdrS' or $ver < 0x201) {		print STDERR "$kernelfile: not a Linux kernel image\n";		return;	}	$bigker = ($flags & 0x1);	$kernelseg = { file => $ARGV[0],		segment => $bigker ? 0x10000 : 0x1000,		maxlen => $bigker ? undef : 1024 * 512, 		fromoff => $setupsects * 512 + 512,		id => 20,		end => 1 };	$ramdiskseg = { file => $ramdisk,		segment => 0x10000,		align => 4096,		id => 21,		end => 1 };	$$kernelseg{'end'} = 0 if (defined($ramdisk));	$module->add_segment($setupdesc);	$module->add_segment($paramseg);	$module->add_segment($bootseg);	$module->add_segment($setupseg);	$kernellen = $module->add_segment($kernelseg);	if (!$bigker and $kernellen > (($relocseg - 0x1000) * 16)) {		print STDERR "Warning, zImage kernel may collide with Etherboot\n";	}	# Put ramdisk following kernel at next 4096 byte boundary	$$ramdiskseg{'segment'} += (($kernellen + 0xFFF) & ~0xFFF) >> 4 if ($bigker);	# should be 0, 1 or 2 depending on rdbase	$module->add_segment($ramdiskseg, "\x00") if (defined($ramdisk));	$module->dump_segments();	$module->copy_file($setupdesc);	$module->copy_string($paramseg);	$module->copy_file($bootseg);	$module->copy_file($setupseg);	$module->copy_file($kernelseg);	$module->copy_file($ramdiskseg) if (defined($ramdisk));}sub get_geom ($$){	my ($file, $block) = @_;	my ($usedsize, $declsize, $firsttracksize, $geom_string, $fstype);	my ($secttot, $secttrk, $heads, $bigsectors, $bootid, $sig, $cyltot);	($usedsize = $squashfd ? &TruncFD::truncfd($file) : -s $file) > 0		or die "Error reading $file\n";	(undef, $secttot, undef, $secttrk, $heads, undef, $bigsectors, $bootid, undef,		$fstype, $sig) = unpack('a19va3vva4VCa17a5@510a2', $$block);	print STDERR "Warning, this doesn't appear to be a DOS boot sector\n"		if ($sig ne "\x55\xAA");		if ($secttot == 0) {	    $secttot = $bigsectors;	}		print STDERR "Geometry...\n";	print STDERR "totSect:$secttot,spt:$secttrk,hd:$heads,bid:$bootid,fsType:$fstype,sig:$sig,simhd:$simhd\n";	if ($simhd) {		# change MediaDescriptor		substr($$block, 0x15, 1) = "\xF8";		# change HiddenSectors		substr($$block, 0x1c, 4) = pack('V', $secttrk);		# change the boot drive		substr($$block, 0x24, 1) = "\x80";	}	$cyltot = $secttot / ($secttrk * $heads);	$declsize = $secttot * 512;	$firsttracksize = $secttrk * 512;	print STDERR "Warning, used size $usedsize is greater than declared size $declsize\n"		if ($usedsize > $declsize);			print STDERR "cyl:$cyltot,decl_size:$declsize,used_size:$usedsize\n";			$geom_string = pack('Vv3C2', $secttot, $heads, $secttrk, $cyltot, $simhd ? 0x80 : 0, $dishd);	return ($usedsize, $declsize, $firsttracksize, $geom_string, $fstype);}sub mod_geom_string ($){	my ($geom_string) = @_;	my ($secttot, $heads, $secttrk, $cyltot, $simhd, $dishd) = unpack('Vv3C2', $geom_string);	$cyltot++;	# for partition table	return (pack('Vv3C2', $secttot, $heads, $secttrk, $cyltot, $simhd, $dishd));}sub encode_chs ($$$){	my ($c, $h, $s) = @_;	$s = ($s & 0x3F) | (($c & 0x300) >> 2);	$c &= 0xFF;	return ($h, $s, $c);}sub make_mbr ($$){	my ($geom_string, $fstype) = @_;	my ($bootsect);	my ($secttot, $heads, $secttrk, $cyltot, $simhd, $x) = unpack('Vv3C2', $geom_string);	$cyltot--;	# $cyltot was incremented in mod_geom_string#	$heads = $secttot / ($secttrk * $cyltot);	# bootsect is first sector of track 1	$bootsect = $secttrk;		print STDERR "--- Making MBR\n";	print STDERR "cyls:$cyltot,heads:$heads,spt:$secttrk,totalSect:$secttot,FSTYPE:$fstype,BS:$bootsect\n";		# CHS stupidity:	# cylinders is 0 based, heads is 0 based, but sectors is 1 based	# 0x01 for FAT12, 0x04 for FAT16	return (pack('@446C8V2@510v', 0x80, &encode_chs(0, 1, 1),		$fstype eq 'FAT12' ? 0x01 : 0x04, &encode_chs($cyltot, $heads - 1, $secttrk),		$bootsect, $secttot, 0xAA55));}sub mknbi_fdos ($){	my ($module) = @_;	my ($setupfile, $bootblock);	my ($usedsize, $declsize, $firsttracksize, $geom_string, $fstype);	my ($setupdesc, $kerneldesc, $firsttrackdesc, $bootdesc, $floppydesc);	my $elfformat = ($format eq 'elf');	$setupfile = "$libdir/" . ($elfformat ? "first-elf.fdos" : "first.fdos");	$#ARGV >= 1 or die "Usage: $0 kernel.sys floppyimage\n";	return unless check_file($setupfile, $ARGV[0], $ARGV[1]);	$module->add_header("mknbi-fdos-$version", $relocseg, $relocseg + ($elfformat ? 0x300 : 0x200), 0);	$setupdesc = { file => $setupfile,		segment => $relocseg + 0x200,		maxlen => 8192,		id => 16 };	$kerneldesc = { file => $ARGV[0],		segment => @@FDKSEG@@,		id => 17 };	die "Ramdisk base should be of the form 0xNNNNNNNN (linear hex address)\n"		if (defined($rdbase) and $rdbase !~ /^0x[\da-fA-F]{1,8}$/);	$floppydesc = { file => $ARGV[1],		segment => (defined($rdbase) ? (hex($rdbase) >> 4) : 0x11000),		id => 18,		end => 1 };	$module->add_segment($setupdesc);	$module->add_segment($kerneldesc);	$module->peek_file($floppydesc, \$bootblock, 512) == 512		or die "Error reading boot sector of $ARGV[1]\n";	($usedsize, $declsize, $firsttracksize, $geom_string, $fstype)		= &get_geom($ARGV[1], \$bootblock);	$firsttrackdesc = { align => $firsttracksize };	$$floppydesc{'fromoff'} = 512;	$$floppydesc{'len'} = $usedsize;	$$floppydesc{'len'} += $firsttracksize if $simhd;	$$floppydesc{'maxlen'} = $declsize;	$geom_string = &mod_geom_string($geom_string) if $simhd;	$module->add_segment($floppydesc, $geom_string);	$module->dump_segments();	$module->copy_file($setupdesc);	$module->copy_file($kerneldesc);	if ($simhd) {		$$firsttrackdesc{'string'} = &make_mbr($geom_string, $fstype);		$module->copy_string($firsttrackdesc);	}	# write out modified bootblock, not the one in the file	$bootdesc = { string => $bootblock };	$module->copy_string($bootdesc);	# Restore correct value of len and account for bootblock skipped	$$floppydesc{'len'} = $usedsize - 512;	$module->copy_file($floppydesc);}sub mknbi_dos ($){	my ($module) = @_;	my ($setupfile, $bootblock);	my ($usedsize, $declsize, $firsttracksize, $geom_string, $fstype);	my ($setupdesc, $firsttrackdesc, $bootdesc, $floppydesc);	my $elfformat = ($format eq 'elf');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -