Other Using dd to copy mbr

I'm trying to copy the first 440 bytes of data from one disk to another using:-

dd if=/dev/da1 if=dev/da0 bs=440 count=1

and get:-

dd: /dev/da1: Invalid argument

Is this to be expected?

How do I achieve what I want to achieve?
 
dev/da0 is not a correct path, it is missing "/" at the beginning of the path, you have also declared two input devices, you need to declare one of them as output, on the other hand the MBR is located in the first sector of the disk, Assuming that the sectors of your disk are 512bytes it would be like this:

I assume da0 is the output device.

dd if=/dev/da1 of=/dev/da0 bs=512 count=1

EDIT:

What is the reason for the block size in 440bytes?

Check the sectorsize of the two devices:


ls -1 /dev/da[0,1] |xargs diskinfo -v |grep -e sectorsize
 
To expand on what covecat said: Disks are block devices. The hardware can only read and write whole blocks of data. The block length is typically 512 or 4096 bytes.

What really happens when you use dd to read or write a different number of bytes? Good question. On reading, I suspect that the hardware reads a whole block, and then the dd program only gets the first 440 bytes returned, and the remaining 72 or 3656 bytes coming from the disk are ignored. On writes, I'm pretty sure the action write system call will fail, probably with "invalid argument". If you really want to write 440 bytes, you need to decide what to do with the extra 72 or 3656 bytes. The easiest might be to zero-pad the 440 bytes, and dd even have an option to do that automatically (but doing it would probably require specifying ibs and obs separately). If one wants to keep the last 72 or 3656 bytes on disk unmolested, one would have to perform a read-modify-write operation, as covecat did. This means having to take the desired new 440 bytes, and the remainder from the old sector, stitching them together (as covecat's little script does), then write it back.
 
he wants to copy only the bootcode without the partition table

Yes; specifically wanting to keep the partition table on the destination disk unmodified.

dd if=/dev/source bs=512 count=1|head -c 446 >/tmp/head
dd if=/dev/dest bs=512 count=1|tail -c 66 >/tmp/tail
cat /tmp/head /tmp/tail|dd of=/dev/dest bs=512

bs always defaults to 512 with dd whatever disk blocksize, so is superfluous, but yes this is the safe way without getting into using different ibs and obs block sizes, skip and/or seek, adding conv=notrunc to the output dd ...

dd direct to live media is for the brave; intermediate files leave a chance to examine them first with say hd(1).

Luigi Rizzo's picobsd build script merrily injected bytes or strings into mid-block of boot files using such techniques. picobsd was removed before 13.0-RELEASE but here's a cute sample from 12.4 /release/picobsd/build/picobsd
Code:
# dump the primary and secondary boot
# XXX primary is 512 bytes
dd if=${c_boot1} of=${BUILDDIR}/${c_img} conv=notrunc 2>/dev/null
# XXX secondary starts after the 0x114 = dec 276 bytes of the label
# so we skip 276 from the source, and 276+512=788 from dst
# the old style blocks used 512 and 1024 respectively
dd if=${c_boot2} iseek=1 ibs=276 2> /dev/null | \
    dd of=${BUILDDIR}/${c_img} oseek=1 obs=788 conv=notrunc 2>/dev/null

And 446 is correct, leaving 66 bytes alone; 4 x 16 byte slice entries plus 2 byte signature '0x55 0xaa'

cheers
 
I'm trying to copy the first 440 bytes of data from one disk to another using:-

dd if=/dev/da1 if=dev/da0 bs=440 count=1
No, you’re not. There are two if=….​
dd if=/dev/source bs=512 count=1|head -c 446 >/tmp/head
dd if=/dev/dest bs=512 count=1|tail -c 66 >/tmp/tail
cat /tmp/head /tmp/tail|dd of=/dev/dest bs=512
It’s definitely good to know what’s happening, but the high‑level variant would be something like:​
Bash:
head -c 512 /dev/da1 > block0
gpart bootcode -b block0 da0
[sup]gpart(8) wants a regular file, so <(head -c 512 /dev/da1) cannot be used as it produces a temporary named FIFO.[/sup]​
 
Why do I get:

dd: /dev/da0: Invalid argument
when running :-

dd status=progress if=boot/boot.img of=/dev/da0 bs=1 count=446

Am I correct in thinking that I can't use bs=1 on FreeBSD? It looks like I can on Linux.
 
you cant use a bs which is not a multiple of the device native block size (for block devices)
for char devs, files any number is valid
 
dd status=progress if=boot/boot.img of=/dev/da0 bs=1 count=446

Are you sure "boot/boot.img" will be found from the current directory when you run this?

You also need conv=notrunc on output files or devices - unless you want the output to be truncated after your block, possibly zeroed.

You could also use [...] bs=446 count=1 conv=notrunc

Am I correct in thinking that I can't use bs=1 on FreeBSD? It looks like I can on Linux.

There are some considerable differences between FreeBSD and Linux dd implementations; best not expect FreeBSD's dd to do other than exactly what's in dd(1).

That said, yes, bs=1 is valid.
 
How to achieve this on FreeBSD?

Bash:
echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none

I think '\x22' is the same as '"' and '\x23' is '#'.
 
There are some considerable differences between FreeBSD and Linux dd implementations; best not expect FreeBSD's dd to do other than exactly what's in dd(1).

That said, yes, bs=1 is valid.
From what was said earlier, it seems bs=1 is only valid on files.

FreeBSD:

Bash:
root@X1:~ # dd if=/dev/da0 of=da0-512-bytes bs=1 count=512
dd: /dev/da0: Invalid argument
0+0 records in
0+0 records out
0 bytes transferred in 0.000094 secs (0 bytes/sec)

Linux:

Bash:
root@x61 # dd if=/dev/sdb of=da0-512-bytes bs=1 count=512
1+0 records in
1+0 records out
1 byte copied, 0.000188367 s, 5.3 kB/s

Interesting that on Linux bs=1 count=512 results in only 1 byte being copied.
 
?‍? I think the confusing part is: “Invalid argument” is the strerror(3) representation of the EINVAL errno(2) number returned by read(2). (source)

You have not provided invalid arguments on the command line. However, in your case the read(2) system call requests 1 Byte chunks. The block device in question cannot provide 1 Byte chunks though, so it fails with an invalid argument error and this is what you see. Run truss(1) to see that (what I just wrote).​
How to achieve this on FreeBSD?
You don’t unless you understand what you’re doing. And why. And tell us your intentions. ?​
I think '\x22' is the same as '"' and '\x23' is '#'.
You flip a bit and this bit flip probably has some meaning, certain consequences, for the stage 0 boot loader installed. For that you must study the bootcode you installed (its documentation or source code).​
[…] Linux dd implementations […]
There is no “Linux dd”. ? Probably the most common in desktop environments is the GNU coreutils implementation, but you could just as well use the Busybox or any other implementation.​
Am I right in thinking that this is supposed to insert '\x22' in position 92 of the mbr?
Yeah, enumerating all output blocks from zero the 93rd output block is overwritten (regardless whether it resembles an MBR).​
 
That said, yes, bs=1 is valid.

Correction: yes valid for files, but not for block devices like disks on FreeBSD. I've just done some tests to confirm.

From what was said earlier, it seems bs=1 is only valid on files.

So the method of working with files, then writing out the final result to disk is the way to go.

FreeBSD:
Bash:
root@X1:~ # dd if=/dev/da0 of=da0-512-bytes bs=1 count=512
dd: /dev/da0: Invalid argument
0+0 records in
0+0 records out
0 bytes transferred in 0.000094 secs (0 bytes/sec)

Yes, assuming /dev/da0 exists so being missing isn't the error.

Linux:
Bash:
root@x61 # dd if=/dev/sdb of=da0-512-bytes bs=1 count=512
1+0 records in
1+0 records out
1 byte copied, 0.000188367 s, 5.3 kB/s
Interesting that on Linux bs=1 count=512 results in only 1 byte being copied.

Likely needed conv=notrunc, but I've no GNU system to test.

I'd still suggest avoiding direct comparisons between dd syntax and/or behavior of FreeBSD and GNUs; for what you're attempting you need to extract the intent of code, to craft that in FreeBSD, example next post ...
 
How to achieve this on FreeBSD?

Bash:
echo -en '\x22' | dd status=none of=$DISK conv=fsync bs=1 count=1 seek=92

As above, you need to read, modify then write sector 0 of $DISK. And echo -en with '\x22' is invalid FreeBSD syntax.

Also, none of FreeBSD/boot/{mbr,boot0,boot1} have anything apparently useful at byte 92; that seems to refer to Ventoy's own mbr - and later, bootblocks files.

We've been here before, again:

dd & stdin Oct 26, 2023
https://forums.freebsd.org/threads/dd-stdin.90722/

Porting Ventoy Oct 24, 2023
https://forums.freebsd.org/threads/porting-ventoy.90697/

Code:
xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2014 seek=34
echo -en '\x23' | dd of=$DISK conv=fsync bs=1 count=1 seek=17908 status=none

And that's clearly for GPT, to skip past partition tables.

I think '\x22' is the same as '"' and '\x23' is '#'.

Yes, but what's there before the change, and why is it being done?

You certainly have cut out a big job for yourself. I can't play anymore, it's just endless ...
 
As above, you need to read, modify then write sector 0 of $DISK. And echo -en with '\x22' is invalid FreeBSD syntax.

What I have found is that

gpart bootcode -b (VT)boot.img

shows VT when trying to boot, but if I try injecting '\x22' into the boot.img file using

echo -n '"' | dd status=none of=$MBR conv=fsync bs=1 count=1 seek=92
it doesn't show anything. AIUI echo -n '"' is equivalent to Linux's

echo -en '\x22'.

It would be interesting to know what is so significant about byte 92 in Ventoy's mbr.
 
he wants to copy only the bootcode without the partition table

dd if=/dev/source bs=512 count=1|head -c 446 >/tmp/head
dd if=/dev/dest bs=512 count=1|tail -c 66 >/tmp/tail
cat /tmp/head /tmp/tail|dd of=/dev/dest bs=512

Given that blob exists, is there anything wrong 'syntactically' with this:

cat `head -c 440 blob` | dd status=progress of=/dev/da0 bs=512

I've been trying to get this working for ages, cut it doesn't want to work. I can't see what's wrong.
 
Given that blob exists, is there anything wrong 'syntactically' with this:

cat `head -c 440 blob` | dd status=progress of=/dev/da0 bs=512

Try adding conv=notrunc to the dd, otherwise dd will attempt to truncate the output after 440 (should be 446!) bytes.

dd if=/dev/da0 count=1 | hd
to show the result.
 
Try adding conv=notrunc to the dd, otherwise dd will attempt to truncate the output after 440 (should be 446!) bytes.

dd if=/dev/da0 count=1 | hd
to show the result.

Is this syntactically correct?

Code:
echo 'bla di bla bla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di blabla di bla ' >blob

cat blob

cat `head -c 40 blob` | dd status=progress of=/dev/da0 bs=512

I don't understand why I get the following:-

cat: bla: No such file or directory
cat: di: No such file or directory
cat: bla: No such file or directory
cat: bla: No such file or directory
cat: di: No such file or directory
cat: blabla: No such file or directory
cat: di: No such file or directory
cat: blabla: No such file or directory
cat: di: No such file or directory
cat: bl: No such file or directory
 
head -c 40 blob
Code:
bla di bla bla di blabla di blabla di bl
cat `head -c 40 blob` -> cat bla di bla bla di blabla di blabla di bl
How do I pipe the output of head -c 40 blob into dd of=/dev/da0 ?

I keep getting 'Invalid argument'.
 
Back
Top