Steps to make a change to a binary (already compiled) kernel
Take a bzImage
Unpack it with mkvmlinux
This will provide you with 3 parts:
bootsector, setup, and system
(Currently the unpacker gives you no permissions, so do chmod a+rw bootsector setup system)
system is composed of (at least) 2 parts
header and data
The data section is the kernel proper in gzip format. You will notice the data (gzipped kernel) begins with the gzip signiture of “1f 8b 08”. Just prior to this is just a handfull of values and a lot of “00” padding. The data section in my “system” starts around offset 3650 (IIRC – If I Recall Correctly).
Note what the offset is, then convert that hex value to decimal
bc
ibase=16
3650
Then dd out the header and data
dd if=system of=header bs=1 count=13904
dd if=system of=kernel.gz bs=1 skip=13904
Now unzip the kernel:
gunzip kernel.gz
Now convert to hex and then make any modifications you need to the kernel.
xxd -g 1 kernel kernel.hex
My need is to change the Serial I/O port from 0x3f8 to 0x400, so I find my appropriate section which has “c2 01 00 f8 03” (note that most everything has reverse order), then I make my change to “c2 01 00 00 04”. Now it’s time to repack.
Convert from hex back to binary:
xxd -r kernel.hex kernel.new
Compress the kernel
cat kernel.new | gzip -n9 > kernel.new.gz
The tail end of the header contains the length of the ?gzipped? kernel. So do a ls -l kernel.new.gz and convert that to hex:
bc
obase=16
110506
So that means that you have to convert the header to hex, update the size, then repack it:
xxd -g 1 header header.hex
xxd -r header.hex header.new
Put back the header and kernel:
cat header.new kernel.new.gz > system.new
Now put back the 3 main pieces:
./mkvmlinuz -b -o bzImage.new bootsect setup system.new
Now boot on the new bzImage
Notes:
Make sure that bytes 501 and 500 of are still able to contain the size (in blocks of 16, rounded up) of the system.new.
The above doesn’t have accurate numbers with each of the examples yet.
In the above example my gzipped kernel was 2 bytes larger than the previous. Without updating the header size info I got “ran out of input data”. Now after updating the header size info, I get something like “length error”. So I am still missing a value somewhere.