Steps to make a change to a binary (already compiled) kernel

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


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

Compress the kernel

cat | gzip -n9 >

The tail end of the header contains the length of the ?gzipped? kernel. So do a ls -l and convert that to hex:


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

Put back the header and kernel:
cat >

Now put back the 3 main pieces:

./mkvmlinuz -b -o bootsect setup

Now boot on the new bzImage

Make sure that bytes 501 and 500 of are still able to contain the size (in blocks of 16, rounded up) of the

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.

Categorized as How To Tagged

By shibaa987

Linux kernel developer and a firmware developer with an experience of 10+ years.

Leave a comment

Your email address will not be published. Required fields are marked *