Install FreeBSD bootcode from Linux rescue system

I have a system like this:
gpart show
=> 40 7501476448 nvd0 GPT (3.5T)
40 1024 1 freebsd-boot (512K)
1064 984 - free - (492K)
2048 33554432 2 freebsd-swap (16G)
33556480 7467919360 3 freebsd-zfs (3.5T)
7501475840 648 - free - (324K)
If after a FreeBSD upgrade I forget to update the bootloader then is it possible to install it using a Linux rescue system and command dd?

In the Linux rescue system I can mount the zfs pool:


zpool import -N -R /mnt zroot
zfs mount zroot/ROOT/default


And /mnt/boot/pmbr and /mnt/boot/gptzfsboot are accessible.

And in Linux rescue system the disk is found as: /dev/nvme0n1
 
Do you think these commands are correct?


dd if=/mnt/boot/pmbr of=/dev/nvme0n1 bs=512 count=1
dd if=/mnt/boot/gptzfsboot of=/dev/nvme0n1 bs=512 seek=40
 
Do you think these commands are correct?


dd if=/mnt/boot/pmbr of=/dev/nvme0n1 bs=512 count=1
Nooo! Not 512. You will destroy the partition table. Ok, it's a fake one but... The number of bytes to write is precisely 446. I don't know with linux, but the FreeBSD dd can't write less than 512 bytes IIRC, so this command is a bad idea. I will let the current bootcode. The update of this piece of code brings nothing interesting.

Do you think these commands are correct?


dd if=/mnt/boot/gptzfsboot of=/dev/nvme0n1 bs=512 seek=40
Should work if you remove "seek" and if the linux nvme0n1 is well the FreeBSD nvd0p1.

That said, ataxa1a is right. It would be simpler and less dangerous to use a FreeBSD booting key and use the suited commands.
 
Linux nvme0n1 = FreeBSD nvd0 (not nvd0p1). So I believe seek=40 is needed in this case to skip the first 40 sectors (MBR and unused space) and write into the freebsd-boot partition starting at sector 40. Am I right?
 
Linux nvme0n1 = FreeBSD nvd0 (not nvd0p1). So I believe seek=40 is needed in this case to skip the first 40 sectors (MBR and unused space) and write into the freebsd-boot partition starting at sector 40. Am I right?
Ah ok. Can't you use the partition directly: nvme0n1p1? This is less prone to error.
 
Please use tags code when pasting code, not cmd. It's less error prone to read output such as this one:
Code:
gpart show
=>        40  7501476448  nvd0  GPT  (3.5T)
         40        1024     1  freebsd-boot  (512K)
       1064         984        - free -  (492K)
       2048    33554432     2  freebsd-swap  (16G)
   33556480  7467919360     3  freebsd-zfs  (3.5T)
 7501475840         648        - free -  (324K)

Do you think these commands are correct?


dd if=/mnt/boot/pmbr of=/dev/nvme0n1 bs=512 count=1
dd if=/mnt/boot/gptzfsboot of=/dev/nvme0n1 bs=512 seek=40
We are assuming block size is 512.
In theory these commands do look OK. With few buts and gotchas though..

Emrion did raise few important points, I will address them a bit further.

1) pMBR
It's important to distinguish between legacy boot and UEFI boot with GPT layout. In your case it's the former; pMBR is important.

Simply said pMBR in legacy boot searches for freebsd-boot UUID, loads it into memory and continues there. GPT header/structures are used to get the partition information. Still to preserve the fake partition from your current disk you could do this:
Code:
dd if=/dev/nvd0 of=pmbr bs=512 count=1                                   # save current pmbr
dd if=/boot/pmbr of=./pmbr bs=1 count=446 conv=notrunc      # write 446 (0x1be) to a file, don't truncate the output
dd if=./pmbr of=/dev/nvd0 bs=512 count=1                   # copy it back to nvd0 ; count is not mandatory but it's safer .. you could also check its size before actual dd-ing
You need to do it like this because you can't write less than a block size to a disk.

2) actual FreeBSD bootloader
If you can you should do it as Emrion pointed out - use partition. It will keep you within its limits if something goes wrong. Now we still have a problem - we can't write any size to a disk directly, it has to be in blocks. My current gptzfsboot:
Code:
# ll /boot/gptzfsboot
-r--r--r--  1 root wheel 176358 Nov 29 11:22 /boot/gptzfsboot
Is not .. Your dd will not write all the data which can be a problem.
Code:
dd if=/boot/gptzfsboot of=/dev/nvd0p1 bs=512 conv=sync
Would do the trick.

While it's not mandatory I strictly use iseek/oseek when doing skip/seek. They are aliases that clearly communicate on which side (input/output) skipping/seeking is to be done.
 
Finally in Linux rescue mode (something like mfsBSD but for Linux) I run:

Code:
dd if=/dev/zero of=/dev/nvme0n1p1 bs=512 conv=sync
dd if=/dev/zero of=/dev/nvme1n1p1 bs=512 conv=sync

Then I verified that the system doesn't boot.

Then I boot again in Linux rescue mode and I run:

Code:
zpool import -N  -R /mnt zroot
zfs mount zroot/ROOT/default

dd if=/mnt/boot/gptzfsboot of=/dev/nvme0n1p1 bs=512 conv=sync
dd if=/mnt/boot/gptzfsboot of=/dev/nvme1n1p1 bs=512 conv=sync

Then I verified that the system boots successfully.

Thank you all for the help.
 
Back
Top