Bootable Disk: Difference between revisions
[unchecked revision] | [unchecked revision] |
m (Bot: Replace deprecated source tag with syntaxhighlight) |
|||
(3 intermediate revisions by 3 users not shown) | |||
Line 6: | Line 6: | ||
* fdisk |
* fdisk |
||
* mkfs.vfat |
* mkfs.vfat |
||
* [[bootloader]] |
|||
* [[bootloader]] (see also [[Rolling Your Own Bootloader]] and [[Babystep1]] tutorial) |
|||
* your [[Kernels|kernel]] and maybe some other files |
* your [[Kernels|kernel]] and maybe some other files |
||
Line 12: | Line 12: | ||
=== Creating an Empty Image === |
=== Creating an Empty Image === |
||
First of all, let's create an empty disk image file, let's say 128 megabytes in size. |
First of all, let's create an empty disk image file, let's say 128 megabytes in size. |
||
< |
<syntaxhighlight lang="bash"> |
||
$ dd if=/dev/zero of=diskimage.dd bs=1048576 count=128 |
$ dd if=/dev/zero of=diskimage.dd bs=1048576 count=128 |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Creating the Partitioning Table === |
=== Creating the Partitioning Table === |
||
As the GPT is more complex thing than MBR partitioning tables, we'll use fdisk, which has an interactive interface (for macOS you will need to |
As the GPT is more complex thing than MBR partitioning tables, we'll use fdisk, which has an interactive interface (for macOS you will need to use the [https://www.gnu.org/software/fdisk/ gnu fdisk]). Inputs (that you're supposed to type) are after the ":" colons. |
||
< |
<syntaxhighlight lang="bash"> |
||
$ fdisk diskimage.dd |
$ fdisk diskimage.dd |
||
Line 45: | Line 45: | ||
The partition table has been altered.Syncing disks. |
The partition table has been altered.Syncing disks. |
||
$ |
$ |
||
</syntaxhighlight> |
|||
</source> |
|||
The commands used were: |
The commands used were: |
||
* g - create a new GPT partitioning table |
* g - create a new GPT partitioning table |
||
Line 56: | Line 56: | ||
=== Creating a File System on the First Partition === |
=== Creating a File System on the First Partition === |
||
Now this is not at simple as it seems, because we have to create the file system somewhere in the middle of a file. For that, we'll create a [[Loopback_Device|loop device]]. |
Now this is not at simple as it seems, because we have to create the file system somewhere in the middle of a file. For that, we'll create a [[Loopback_Device|loop device]]. |
||
< |
<syntaxhighlight lang="bash"> |
||
$ losetup -o $[2048*512] --sizelimit $[8*1024*1024] -f diskimage.dd |
$ losetup -o $[2048*512] --sizelimit $[8*1024*1024] -f diskimage.dd |
||
</syntaxhighlight> |
|||
</source> |
|||
Here the arguments are: |
Here the arguments are: |
||
* -o $[2048*512] - tells losetup that our partition is starting at the 2048th sector (one sector is 512 bytes) |
* -o $[2048*512] - tells losetup that our partition is starting at the 2048th sector (one sector is 512 bytes) |
||
Line 65: | Line 65: | ||
* and the last parameter is our disk image's filename. |
* and the last parameter is our disk image's filename. |
||
To see which device was used for your image, you can do |
To see which device was used for your image, you can do |
||
< |
<syntaxhighlight lang="bash"> |
||
$ losetup -a |
$ losetup -a |
||
</syntaxhighlight> |
|||
</source> |
|||
which will list all loopback devices. |
which will list all loopback devices. |
||
Now that we have a device which points inside the image file exactly to the partition, we can create a FAT filesystem on it: |
Now that we have a device which points inside the image file exactly to the partition, we can create a FAT filesystem on it: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ mkfs.vfat -F 16 -n "EFI System" /dev/loop0 |
$ mkfs.vfat -F 16 -n "EFI System" /dev/loop0 |
||
</syntaxhighlight> |
|||
</source> |
|||
Here |
Here |
||
* -F 16 - tells to create a FAT16 |
* -F 16 - tells to create a FAT16 |
||
Line 81: | Line 81: | ||
=== Adding Files to the Partition === |
=== Adding Files to the Partition === |
||
The next step is to mount our loopback device, so that we can copy files to the partition. |
The next step is to mount our loopback device, so that we can copy files to the partition. |
||
< |
<syntaxhighlight lang="bash"> |
||
$ mkdir somedir |
$ mkdir somedir |
||
$ mount /dev/loop0 somedir |
$ mount /dev/loop0 somedir |
||
</syntaxhighlight> |
|||
</source> |
|||
For simplicity, let's call our kernel MSDOS.SYS and out configuration file CONFIG.SYS: |
For simplicity, let's call our kernel MSDOS.SYS and out configuration file CONFIG.SYS: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ cp MSDOS.SYS CONFIG.SYS somedir/ |
$ cp MSDOS.SYS CONFIG.SYS somedir/ |
||
</syntaxhighlight> |
|||
</source> |
|||
Some boot loaders are so called two-stage loaders. This means they have two parts: a boot sector and a 2nd stage file. You must copy that 2nd stage to the partition: |
Some boot loaders are so called two-stage loaders. This means they have two parts: a boot sector and a 2nd stage file. You must copy that 2nd stage to the partition: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ cp 2NDSTAGE.BIN somedir/ |
$ cp 2NDSTAGE.BIN somedir/ |
||
</syntaxhighlight> |
|||
</source> |
|||
[[UEFI]] will need a special [[PE]] executable named '''EFI/BOOT/BOOT(arch).EFI''', which you can create with [[GNU-EFI]]: |
[[UEFI]] will need a special [[PE]] executable named '''EFI/BOOT/BOOT(arch).EFI''', which you can create with [[GNU-EFI]]: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ mkdir somedir/EFI somedir/EFI/BOOT |
$ mkdir somedir/EFI somedir/EFI/BOOT |
||
$ cp BOOTX64.EFI somedir/EFI/BOOT |
$ cp BOOTX64.EFI somedir/EFI/BOOT |
||
</syntaxhighlight> |
|||
</source> |
|||
Once you're finished with the copy, it is important to dismount the partition: |
Once you're finished with the copy, it is important to dismount the partition: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ umount somedir |
$ umount somedir |
||
$ rmdir somedir |
$ rmdir somedir |
||
</syntaxhighlight> |
|||
</source> |
|||
=== Adding the BIOS Boot Loader === |
=== Adding the BIOS Boot Loader === |
||
If you're planning to create a hybrid image with the PMBR (that you can also boot on legacy BIOS machines), then you need to add the legacy BIOS boot loader code: |
If you're planning to create a hybrid image with the PMBR (that you can also boot on legacy BIOS machines), then you need to add the legacy BIOS boot loader code: |
||
< |
<syntaxhighlight lang="bash"> |
||
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=446 count=1 |
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=446 count=1 |
||
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=1 count=2 skip=510 seek=510 |
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=1 count=2 skip=510 seek=510 |
||
</syntaxhighlight> |
|||
</source> |
|||
The first command copies the code, and the second one the two magic bytes at the end of the sector. This way the bytes 446 - 510 (where the partitioning table resides) won't be overwritten. It is very important preserve the ESP entry required by UEFI. |
The first command copies the code, and the second one the two magic bytes at the end of the sector. This way the bytes 446 - 510 (where the partitioning table resides) won't be overwritten. It is very important preserve the ESP entry required by UEFI. |
||
Line 127: | Line 127: | ||
* [[EFI System Partition]] |
* [[EFI System Partition]] |
||
[[Category:Booting]] |
|||
[[Category:Tutorials]] |
[[Category:Tutorials]] |
Latest revision as of 04:12, 9 June 2024
This brief tutorial is about how to create your own bootable disk image. For information about partitioning see GPT and FAT.
Difficulty level |
---|
![]() Beginner |
Requirements
you'll need the following:
- fdisk
- mkfs.vfat
- bootloader
- your kernel and maybe some other files
Required Steps
Creating an Empty Image
First of all, let's create an empty disk image file, let's say 128 megabytes in size.
$ dd if=/dev/zero of=diskimage.dd bs=1048576 count=128
Creating the Partitioning Table
As the GPT is more complex thing than MBR partitioning tables, we'll use fdisk, which has an interactive interface (for macOS you will need to use the gnu fdisk). Inputs (that you're supposed to type) are after the ":" colons.
$ fdisk diskimage.dd
Welcome to fdisk (util-linux 2.30.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xfa00b86e.
Command (m for help): g
Created a new GPT disklabel (GUID: E6B4945A-8308-448B-9ACA-0E656854CF66).
Command (m for help): n p
Partition number (1-128, default 1): 1
First sector (2048-262110, default 2048): 2048
Last sector, +sectors or +size{K,M,G,T,P} (2048-262110, default 262110): +8M
Created a new partition 1 of type 'Linux filesystem' and of size 8 MiB.
Command (m for help): t 1
Selected partition 1
Partition type (type L to list all types): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.
Command (m for help): w
The partition table has been altered.Syncing disks.
$
The commands used were:
- g - create a new GPT partitioning table
- n p - new primary partition
- 1 2048 +8M - first partition, starting sector, partition size
- t 1 - change the type of the first partition
- 1 - type 1 is EFI System Partition (or ESP in short)
- w - write out changes
Creating a File System on the First Partition
Now this is not at simple as it seems, because we have to create the file system somewhere in the middle of a file. For that, we'll create a loop device.
$ losetup -o $[2048*512] --sizelimit $[8*1024*1024] -f diskimage.dd
Here the arguments are:
- -o $[2048*512] - tells losetup that our partition is starting at the 2048th sector (one sector is 512 bytes)
- --sizelimit $[8*1024*1024] - specifies the limit in 8 megabytes
- -f - tells to find a suitable loopback device
- and the last parameter is our disk image's filename.
To see which device was used for your image, you can do
$ losetup -a
which will list all loopback devices.
Now that we have a device which points inside the image file exactly to the partition, we can create a FAT filesystem on it:
$ mkfs.vfat -F 16 -n "EFI System" /dev/loop0
Here
- -F 16 - tells to create a FAT16
- -n "EFI System" - sets the label for the partition (don't change, some firmware checks for this)
- /dev/loop0 - is the loopback device (change to the one you saw in losetup -a output)
Adding Files to the Partition
The next step is to mount our loopback device, so that we can copy files to the partition.
$ mkdir somedir
$ mount /dev/loop0 somedir
For simplicity, let's call our kernel MSDOS.SYS and out configuration file CONFIG.SYS:
$ cp MSDOS.SYS CONFIG.SYS somedir/
Some boot loaders are so called two-stage loaders. This means they have two parts: a boot sector and a 2nd stage file. You must copy that 2nd stage to the partition:
$ cp 2NDSTAGE.BIN somedir/
UEFI will need a special PE executable named EFI/BOOT/BOOT(arch).EFI, which you can create with GNU-EFI:
$ mkdir somedir/EFI somedir/EFI/BOOT
$ cp BOOTX64.EFI somedir/EFI/BOOT
Once you're finished with the copy, it is important to dismount the partition:
$ umount somedir
$ rmdir somedir
Adding the BIOS Boot Loader
If you're planning to create a hybrid image with the PMBR (that you can also boot on legacy BIOS machines), then you need to add the legacy BIOS boot loader code:
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=446 count=1
$ dd if=boot.bin of=diskimage.dd conv=notrunc bs=1 count=2 skip=510 seek=510
The first command copies the code, and the second one the two magic bytes at the end of the sector. This way the bytes 446 - 510 (where the partitioning table resides) won't be overwritten. It is very important preserve the ESP entry required by UEFI.
Here the arguments mean:
- if=boot.bin - the name of the boot loader, should be 512 bytes
- of=diskimage.dd - the disk image
- conv=notrunc - tells dd to update an existing image file instead of creating a new one
- bs=446 - block size (sector size is 512 bytes, but we want to write less)
- skip=510 - skip that many blocks (in second line bs is 1, so skip 510 bytes)
- count=1 - tells dd to update one sector only