BIOS / MBR based disks layout in FreeBSD is messy as historically this created a single Partition and then the FreeBSD UFS files systems was embedded inside this. To convert your machine to UEFI/GPT based one you will need to make sure you have FreeBSD 7 or greater (to get GPT support) and be able to use the FreeBSD command line disk partitioning tools.
Status: 16 Sept 2020 / Late Dec 2010 - Writing up so as not to forget
I have a number of FreeBSD VMs that were build on old FreeBSD version with MBR based disks. To help move these across to newer FreeBSD version I need to first move the disk to GPT and change them from bios to UEFI bootable.
Here is the process:
- Add new disk to your machine
- Boot from CDROM
- Create new GPT partition on the new disk
- Add FAT partition for UFI boot
- If you old disk is slit up into individual partitions then decide if you want to bring everything together under a single root partition
- Create new UFS partition/s on new disk
- Copy partitions from old to new disk
- Setup UEFI
- Update /etc/fstab to reflect new layout
NOTE: I have done this with 64 bit FreeBSD versions succesfully only. I had not had success with 32 bit FreeBSD and UEFI boot.
List disks & get partition information
In FreeBSD you can find disk by looking at the /dev tree for ad, cd, da and other disk device name or list the "geometry class device" (from the day of spinning disk): "geom disk list" and the partition information via "df" and reviewing "/etc/fstab" & /dev file system:
--- --- show the attached disk --- # geom disk list Geom name: da0 Providers: 1. Name: da0 Mediasize: 10737418240 (10G) Sectorsize: 512 Mode: r5w5e14 fwsectors: 63 fwheads: 255 --- --- show the partition type --- # gpart show da0 => 63 20971440 da0 MBR (10G) <<=== MBR 63 20964762 1 freebsd [active] (10G) 20964825 6678 - free - (3.3M) --- --- do ls of /dev/da0* to see partitions --- dispute-db# ls /dev/da0* /dev/da0 /dev/da0s1a /dev/da0s1d /dev/da0s1f /dev/da0s1 /dev/da0s1b /dev/da0s1e --- --- NOTE: The MBR partitioning show the each of the partitions as letter --- With GPT partitions are given numbers... --- To see which partition are associated with which dev --- do df and look at fstab --- # df -h Filesystem Size Used Avail Capacity Mounted on /dev/da0s1a 1.9G 213M 1.6G 12% / devfs 1.0K 1.0K 0B 100% /dev /dev/da0s1d 989M 64K 910M 0% /tmp /dev/da0s1f 2.9G 2.1G 590M 78% /usr /dev/da0s1e 1.9G 113M 1.7G 6% /var --- --- The missing partition from report is /dev/da0s1b which is swap --- as is seen via fstab --- # cat /etc/fstab # Device Mountpoint FStype Options Dump Pass# /dev/da0s1b none swap sw 0 0 /dev/da0s1a / ufs rw 1 1 /dev/da0s1d /tmp ufs rw 2 2 /dev/da0s1f /usr ufs rw 2 2 /dev/da0s1e /var ufs rw 2 2 /dev/acd0 /cdrom cd9660 ro,noauto 0 0 --- --- Ok now we have all the informaiton on MBR partitioned file-system ---
Create GPT Disk with EFI Partition
Having found the details of your disk (see "List disks & get partition information") above you can now determine which disk partitions can available to mount.
In my case I had 2 disk:
da0 - orginal FreeBSD with MBR partitioning using entire disk and connected via QEMU lsi1068 SCSI controller.
ad8 - the target SATA connected disk that will be GPT partitioned and in this case I will partition this as follows:
- efi (fat16) - this is UEFI boot partition which is formatted as FAT16 and will contain the replacement for the MBR boot record
- freebsd-ufs - create a single UFS partition and copy all the previously seperate: / (root), /usr, /var & /tmp partitions content to this, so that it consolidates under single partition, as having physical seperation is not required in virtual environment.
- freebsd-swap - use remaining space for swap
NOTE: The following example uses tiny disk for illustrative purposes.
To create new GPT / EFI ready disk use gpart to: create GPT partitioned disk and then add the 3 partitions as above:
--- --- 1. Create GPT partition -- # gpart create -s GPT ad8 ad8 created # gpart show ad8 => 34 4194237 ad8 GPT (2.0G) 34 4194237 - free - (2.0G) --- --- 2. Now add 200M efi boot partition --- dispute-db# gpart add -t efi -s 200M -i 1 ad8 ad8p1 added # gpart show ad8 => 34 4194237 ad8 GPT (2.0G) 34 409600 1 efi (200M) 409634 3784637 - free - (1.8G) --- --- 3. Add the ufs file-system partition --- # gpart add -t freebsd-ufs -s 1G -i 2 ad8 ad8p2 added # gpart show ad8 => 34 4194237 ad8 GPT (2.0G) 34 409600 1 efi (200M) 409634 2097152 2 freebsd-ufs (1.0G) 2506786 1687485 - free - (824M) --- --- 4. Use the remaining space for SWAP, this is optional --- dispute-db# gpart add -t freebsd-swap -i 3 ad8 ad8p3 added dispute-db# gpart show ad8 => 34 4194237 ad8 GPT (2.0G) 34 409600 1 efi (200M) 409634 2097152 2 freebsd-ufs (1.0G) 2506786 1687485 3 freebsd-swap (824M) --- --- 5. Create file systems --- # newfs_msdos /dev/ad8p1 newfs_msdos: trim 37 sectors to adjust to a multiple of 63 /dev/ad8p1: 409328 sectors in 25583 FAT16 clusters (8192 bytes/cluster) BytesPerSec=512 SecPerClust=16 ResSectors=1 FATs=2 RootDirEnts=512 Media=0xf0 FATsecs=100 SecPerTrack=63 Heads=16 HiddenSecs=0 HugeSectors=409563 # newfs /dev/ad8p2 /dev/ad8p2: 1024.0MB (2097152 sectors) block size 16384, fragment size 2048 using 6 cylinder groups of 183.77MB, 11761 blks, 23552 inodes. super-block backups (for fsck -b #) at: 160, 376512, 752864, 1129216, 1505568, 1881920 --- --- 6. Next need to copy from old MBR to new GPT / UEFI ---
NOTE: The /dev disk naming is dependent on the disk driver being used the most common once are:
- ada - SATA on newer FreeBSD
- da - SCSI
- ad - ATA/SATA on older FreeBSD
- vda - VirtIO driver
Hence you should use the "geom drive list" to get right name for you machine.
Clone the disk contents
Having created GPT disk to copy contents to the next thing is to copy content from old disk to new disk.
This can be done with tar or rsync, which you use if personal preference. I have successfully used tar with no issues. With tar the important thing it is to backup from containing directory not from within the containing directory.
The process is:
- Reboot from Live CD
- Mount each of the source and target directories
- Clone the source directory to target
- Copy EFI boot directory contents
- Update "/etc/fstab" to be consistent with new disk driver
Here is sample run on machine booted via install CD and selecting "Live CD" startup:
--- --- Following on from previous example, mount the directorys --- NOTE: This is all done via root login with --- # cd /tmp # mkdir OLD_ROOT OLD_VAR OLD_TMP OLD_USR NEW_ROOT # mount -t ufs /dev/da0s1a /tmp/OLD_ROOT # mount -t ufs /dev/da0s1d /tmp/OLD_TMP # mount -t ufs /dev/da0s1f /tmp/OLD_USR # mount -t ufs /dev/da0s1e /tmp/OLD_VAR # mount -t ufs /dev/ad8s2 /tmp/NEW_ROOT <<=== s2 as s1 is for EFI --- --- Copy the directory contents using tar or rsync --- This example uses tar (if you are rsync expert use that... --- # tar cf - OLD_ROOT | (cd /tmp/NEW_ROOT; tar xvf - --strip-components 1) # tar cf - OLD_VAR | (cd /NEW_ROOT/var; tar xvf - --strip-components 1) # tar cf - OLD_TMP | (cd /NEW_ROOT/tmp; tar xvf - --strip-components 1) # tar cf - OLD_USR | (cd /NEW_ROOT/usr; tar xvf - --strip-components 1)
NOTE: The tar works as it takes a copy of the entire directory tree, so when we restore, we need to strip off the initial directory path, hence "--strip-components 1" option.
This has cloned all the contents from the 4 seperate partitions into single root partition. We now need to copy EFI files into the EFI (FAT32) partition. These on on the CD in the directory /boot. With FreeBSD 11.4 there is an image of the FAT16 boot partition ub: "/boot/boot1.efidat".
This can be mounted and the contents copied over to the new EFI FAT16 partition. (which is copied to efi/boot/BOOTx64.efi). So you can either create the EFI directory by copying from the CD into the EFI partition. The alternative is to simply mount the EFI partition from existing FreeBSD of right version and copy this,.
This example does mount of CDROM image and then copies content across:
--- --- Mount the two EFI partitions --- # cd tmp # mkdir CDROM IN-EFI OUT-EFI --- --- Mount FreeBSD DVD --- # mount -t cd9660 /dev/cd0 /tmp/CDROM --- --- Do loop mount of efi fs image from CD --- # mdconfig -a -t vnode -f CDROM/boot/boot1.efidat md0 <<== The /dev node created by mdconfig # mount -t msdosfs -o ro /dev/md0 /tmp/IN-EFI <<== older FreeBSD uses "-t msdos" --- --- Mount target efi FAT16 partition --- # mount -t msdosfs /dev/ada1s1 /tmp/OUT-EFI --- --- Now copy the files: efi/boot/BOOTx64.efi + efi/boot/startup.nsh --- # cd IN-EFI # cp -R * ../OUT-EFI
The last thing is to check what will be the new "/etc/fstab" file under the NEW_ROOT and ensure it refers to the correct / (root) mount and /dev/<FILE>.
NOTE: mount now uses "-t msdosfs" rather than plain "-t msdos"
Change VM / Machine to UEFI (OVMF) boot
The new disk you have now created is only suitable for UEFI booting. So if you are running this as VM, then you will need to update the VM to use UEFI boot.
On physical machine this is typically done via initial boot systems setup screen (pressing F1 or F10 or some other key at boot).
References & Links:
gpart - the FreeBSD command line disk partitioning tool
BSD Handbook - "17.2 Adding Disks" section provide some initial starter tips, but you will quickly need more information
rsync - to copy the content of old disk to new disk, while preserving all the attributes
tar - another way to copy the contents from old disk to new disk, while preserving the attributes
FreeBSD UEFI Boot - is well described in the man page: uefi
Install UEFI via "gpart bootcode ..." - as outlined in FreeBSD forums, this essentially does equivalent of dd of the "/boot/boot1.efidat" to target efi partition, that I explicitly mounted and copied in my example