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

📄 elf.pm

📁 linux下从网卡远程启动
💻 PM
字号:
# Class to handle Elf images# Placed under GNU Public License by Ken Yap, December 2000package Elf;use strict;use IO::Seekable;use constant;use constant TFTPBLOCKSIZE => 512;# ELF magic header in first 4 bytesuse constant MAGIC => "\x7FELF";# This is defined by the bootrom layoutuse constant HEADERSIZE => 512;# Size of ELF headeruse constant ELF_HDR_LEN => 52;# Type codeuse constant ELFCLASS32 => 1;# Byte orderuse constant ELFDATA2LSB => 1;# ELF versionuse constant EV_CURRENT => 1;# File typeuse constant ET_EXEC => 2;# Machine typeuse constant EM_386 => 3;# Size of each program headeruse constant PROG_HDR_LEN => 32;# Type of headeruse constant PT_LOAD => 1;use constant PT_NOTE => 4;# Size of each section header (there is just one)use constant SECT_HDR_LEN => 40;# Note typesuse constant EIN_PROGRAM_NAME     => 0x00000001;use constant EIN_PROGRAM_VERSION  => 0x00000002;use constant EIN_PROGRAM_CHECKSUM => 0x00000003;sub new {	my $class = shift;	my $self = { };	$self->{libdir} = shift;	$self->{segdescs} = [];	$self->{offset} = 0;	# cumulative offset from beginning of file	$self->{checksum} = 0;	# cumulative checksum of the file	$self->{summed} = 0;	# number of bytes checksummed	$self->{data} = "";	# string buffer containing the output file	bless $self, $class;#	$self->_initialize();	return $self;}sub add_pm_header ($$$$$){	my ($self, $vendorinfo, $headerseg, $bootaddr, $progreturns) = @_;	push(@{$self->{segdescs}}, pack('A4C4@16v2V5v6',		MAGIC, ELFCLASS32, ELFDATA2LSB, EV_CURRENT,		255,		# embedded ABI		ET_EXEC,	# e_type		EM_386, 	# e_machine		EV_CURRENT,	# e_version		$bootaddr,	# e_entry		ELF_HDR_LEN,	# e_phoff		0,		# e_shoff (come back and patch this)		($progreturns ? 0x8000000 : 0),		# e_flags		ELF_HDR_LEN,	# e_ehsize		PROG_HDR_LEN,	# e_phentsize		0,		# e_phnum (come back and patch this)		SECT_HDR_LEN,	# e_shentsize		1,		# e_shnum, one mandatory entry 0		0));		# e_shstrndx	$self->{offset} = HEADERSIZE;}sub compute_ip_checksum{	my ($str) = @_;	my ($checksum, $i, $size, $shorts);	$checksum = 0;	$size = length($$str);	$shorts = $size >> 1;	# Perl has a fairly large loop overhead so a straight forward	# implementation of the ip checksum is intolerably slow.	# Instead we use the unpack checksum computation function,	# and sum 16bit little endian words into a 32bit number, on at	# most 64K of data at a time.  This ensures we do not overflow	# the 32bit sum allowing carry wrap around to be implemented by	# hand.	for($i = 0; $i < $shorts; $i += 32768) {		$checksum += unpack("%32v32768", substr($$str, $i <<1, 65536));		while($checksum > 0xffff) {			$checksum = ($checksum & 0xffff) + ($checksum >> 16);		}	}	if ($size & 1) {		$checksum += unpack('C', substr($$str, -1, 1));		while($checksum > 0xffff) {			$checksum = ($checksum & 0xffff) + ($checksum >> 16);		}	}	$checksum = (~$checksum) & 0xFFFF;	return $checksum;}sub add_summed_data{	my ($self, $str) = @_;	my $new_sum = compute_ip_checksum($str);	my $new = $new_sum;	my $sum = $self->{checksum};	my $checksum;	$sum = ~$sum & 0xFFFF;	$new = ~$new & 0xFFFF;	if ($self->{summed} & 1) {		$new = (($new >> 8) & 0xff) | (($new << 8) & 0xff00);	}	$checksum = $sum + $new;	if ($checksum > 0xFFFF) {		$checksum -= 0xFFFF;	}	$self->{checksum} = (~$checksum) & 0xFFFF;	$self->{summed} += length($$str);	print "$$str";#	$self->{data} .= $$str;#	print STDERR sprintf("sum: %02x %02x sz: %08x summed: %08x\n",#		$new_sum, $self->{checksum}, length($$str), $self->{summed});}# This should not get called as we don't cater for real mode calls but# is here just in casesub add_header ($$$$$){	my ($self, $vendorinfo, $headerseg, $bootseg, $bootoff) = @_;	$self->add_pm_header($vendorinfo, $headerseg, ($bootseg << 4) + $bootoff, 0);}sub roundup ($$){# Round up to next multiple of $blocksize, assumes that it's a power of 2	my ($size, $blocksize) = @_;	# Default to TFTPBLOCKSIZE if not specified	$blocksize = TFTPBLOCKSIZE if (!defined($blocksize));	return ($size + $blocksize - 1) & ~($blocksize - 1);}# Grab N bytes from a filesub peek_file ($$$$){	my ($self, $descriptor, $dataptr, $datalen) = @_;	my ($file, $fromoff, $status);	$file = $$descriptor{'file'} if exists $$descriptor{'file'};	$fromoff = $$descriptor{'fromoff'} if exists $$descriptor{'fromoff'};	return 0 if !defined($file) or !open(R, "$file");	binmode(R);	if (defined($fromoff)) {		return 0 if !seek(R, $fromoff, SEEK_SET);	}	# Read up to $datalen bytes	$status = read(R, $$dataptr, $datalen);	close(R);	return ($status);}# Add a segment descriptor from a file or a stringsub add_segment ($$$){	my ($self, $descriptor, $vendorinfo) = @_;	my ($file, $string, $segment, $len, $maxlen, $fromoff, $align,		$id, $end, $vilen);	$end = 0;	$file = $$descriptor{'file'} if exists $$descriptor{'file'};	$string = $$descriptor{'string'} if exists $$descriptor{'string'};	$segment = $$descriptor{'segment'} if exists $$descriptor{'segment'};	$len = $$descriptor{'len'} if exists $$descriptor{'len'};	$maxlen = $$descriptor{'maxlen'} if exists $$descriptor{'maxlen'};	$fromoff = $$descriptor{'fromoff'} if exists $$descriptor{'fromoff'};	$align = $$descriptor{'align'} if exists $$descriptor{'align'};	$id = $$descriptor{'id'} if exists $$descriptor{'id'};	$end = $$descriptor{'end'} if exists $$descriptor{'end'};	if (!defined($len)) {		if (defined($string)) {			$len = length($string);		} else {			if (defined($fromoff)) {				$len = (-s $file) - $fromoff;			} else {				$len = -s $file;			}			return 0 if !defined($len);		# no such file		}	}	if (defined($align)) {		$len = &roundup($len, $align);	} else {		$len = &roundup($len);	}	$maxlen = $len if (!defined($maxlen));	push(@{$self->{segdescs}}, pack('V8',		PT_LOAD,		$self->{offset},	# p_offset		$segment << 4,		# p_vaddr		$segment << 4,		# p_paddr		$len,			# p_filesz		$len,			# p_memsz == p_filesz		7,			# p_flags == rwx		TFTPBLOCKSIZE));	# p_align	$self->{offset} += $len;	return ($len);			# assumes always > 0}sub pad_with_nulls ($$$){	my ($self, $i, $blocksize) = @_;	$blocksize = TFTPBLOCKSIZE if (!defined($blocksize));	# Pad with nulls to next block boundary	$i %= $blocksize;	if ($i != 0) {		# Nulls do not change the checksum		print "\0" x ($blocksize - $i);#		$self->{data} .= "\0" x ($blocksize - $i);		$self->{summed} += ($blocksize - $i);	}}# Copy data from file to stdoutsub copy_file ($$){	my ($self, $descriptor) = @_;	my ($i, $file, $fromoff, $align, $len, $seglen, $nread, $data, $status);	$file = $$descriptor{'file'} if exists $$descriptor{'file'};	$fromoff = $$descriptor{'fromoff'} if exists $$descriptor{'fromoff'};	$align = $$descriptor{'align'} if exists $$descriptor{'align'};	$len = $$descriptor{'len'} if exists $$descriptor{'len'};	return 0 if !open(R, "$file");	if (defined($fromoff)) {		return 0 if !seek(R, $fromoff, SEEK_SET);		$len = (-s $file) - $fromoff if !defined($len);	} else {		$len = -s $file if !defined($len);	}	binmode(R);	# Copy file in TFTPBLOCKSIZE chunks	$nread = 0;	while ($nread != $len) {		$status = read(R, $data, TFTPBLOCKSIZE);		last if (!defined($status) or $status == 0);		$self->add_summed_data(\$data);		$nread += $status;	}	close(R);	if (defined($align)) {		$self->pad_with_nulls($nread, $align);	} else {		$self->pad_with_nulls($nread);	}	return ($nread);}# Copy data from string to stdoutsub copy_string ($$){	my ($self, $descriptor) = @_;	my ($i, $string, $len, $align, $data);	$string = $$descriptor{'string'} if exists $$descriptor{'string'};	$len = $$descriptor{'len'} if exists $$descriptor{'len'};	$align = $$descriptor{'align'} if exists $$descriptor{'align'};	return 0 if !defined($string);	$len = length($string) if !defined($len);	$data = substr($string, 0, $len);	$self->add_summed_data(\$data);	defined($align) ? $self->pad_with_nulls($len, $align) : $self->pad_with_nulls($len);	return ($len);}sub dump_segments{	my ($self) = @_;	my ($s, $nsegs, @segdescs);	# generate the note header	my $notes = pack('V3Z8S2',		8,			# n_namesz		2,			# n_descsz		EIN_PROGRAM_CHECKSUM,	# n_type		"ELFBoot",		# n_name		0, 			# n_desc (Initial checksum value)		0);			# padding to a 4byte boundary	my $note_len = length($notes);	# Add the note header	push(@{$self->{segdescs}}, pack('V8',		PT_NOTE,		# p_type		HEADERSIZE - $note_len,	# p_offset		0,			# p_vaddr		0,			# p_paddr		$note_len,		# p_filesz		0,			# p_memsz == p_filesz		0,			# p_flags		0));			# p_align						@segdescs = @{$self->{segdescs}};	$nsegs = $#segdescs;	# number of program header entries	# fill in e_phnum	substr($segdescs[0], 44, 2) = pack('v', $nsegs);	# fill in e_shoff to point to a record after program headers	substr($segdescs[0], 32, 4) = pack('V',		ELF_HDR_LEN + PROG_HDR_LEN * $nsegs);	$self->{checksum} = 0;	$self->{summed} = 0;	while ($s = shift(@segdescs)) {		$self->add_summed_data(\$s);	}	# insert section header 0	# we just need to account for the length, the null fill	# will create the record we want	# warn if we have overflowed allocated header area	print STDERR "Warning, too many segments in file\n"		if ($self->{summed} > HEADERSIZE - SECT_HDR_LEN - $note_len);	print "\0" x (HEADERSIZE - $self->{summed});#	$self->{data} .= "\0" x (HEADERSIZE - $self->{summed});	# Write the note header;	seek(STDOUT, HEADERSIZE - $note_len, SEEK_SET) or die "Cannot seek to note header\n";	print "$notes";#	substr($self->{data}, HEADERSIZE - $note_len, $note_len) = $notes}sub finalise_image {	my ($self) = @_;	# Fill in the checksum	seek(STDOUT, HEADERSIZE - 4, SEEK_SET) or die "Cannot seek to checksum\n";	print pack('S', $self->{checksum});#	substr($self->{data}, (HEADERSIZE - 4), 2) = pack('S', $self->{checksum});#	print $self->{data};}1;

⌨️ 快捷键说明

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