Solved dd & stdin

Two things. First, a common complaint about your posts: You need to give more details, and a justification. Why do you want to copy a single character to a device? What are you really trying to accomplish? If we know what your goal is, we can often suggest a solution. And: you simply write "it doesn't work". What does it actually do? Do you get an error message? Does the write silently fail, and on reading it back, you find that the data was never written? Do purple flying elephants emerge from your computer? If you tell us the exact symptoms and error message, we can help debug.

Second, some background knowledge. Sort of "computers 101". It seems to you are trying to write to a disk drive, indicated by the "da" in the device name. Do you understand that disk drives are structures in blocks (commonly called sectors), and that their interface (SATA, SCSI, USB, ...) is organized around reading and writing blocks? And that the hardware is not even capable of writing a single byte, only a block at a time? If you really need to modify a single byte on the disk, and leave the rest of the block unmodified, what you'll have to do is a "read-modify-write" operation; the disk doesn't do that. Now, your next question is going to be: What is the block size? Answer: It depends. On most consumer disks today it is 4096 bytes, but a lot of older 512 byte block disks still exists. Enterprise disks can have interestingly different block sizes. You can find out what the block size is using the camcontrol command.

By the way, there are long discussions around "block" and "character" devices. Originally, that was the distinction between devices (such as a serial port) that can do IO on an arbitrary number of bytes, versus those that can only read/write a block at a time. That distinction then became (mis-) used for other things (such as cachable or not), and I think in today's FreeBSD only character devices exist in practice. But just because it says "character" on the label doesn't mean there isn't a block device in the package :)

Finally: You understand that writing directly to a disk is a foot-shaped gun, and you will likely injure something (most likely your data, but perhaps also your pride)?
 
the hardware is not even capable of writing a single byte, only a block at a time
The impression of the capability of writing a single byte to a disk comes from Linux. Linux' dd will perfectly do that if bs=1 is set.

Offtopic: I have a scenario when this is useful: an embedded system (aarch64) with Linux is capable of booting off one of two partitions, however, the bootloader (LK) knows nothing about it, the only way is to pass the root partition number to the kernel. The kernel, its command line and DTB are fused in another partition. Using dd I can easily update 2 bytes on the disk (EMMC) to change the partition number in the kernel's command line.
 
How do I copy a single character to a device?

This doesn't work:-

echo -n '\x22' | dd of=/dev/da0

Is this doable?
Since you can only write one or more disk blocks (block size can be 512 or 4K etc.), if you want to *overwrite* a byte, what you have to do is read a block from the disk, then overwrite the byte you want, then write it out. But keep in mind what ralphbsz said re footshooting!
 
The impression of the capability of writing a single byte to a disk comes from Linux. Linux' dd will perfectly do that if bs=1 is set.
Even more off-topic: When you do this in Linux to a disk (and your EMMC is a disk in the sense of using a block protocol), do you know whether it will perform a read-modify-write cycle? Or will it pad the partial block with zeroes?
 
Two things. First, a common complaint about your posts: You need to give more details, and a justification. Why do you want to copy a single character to a device? What are you really trying to accomplish? If we know what your goal is, we can often suggest a solution. And: you simply write "it doesn't work". What does it actually do? Do you get an error message?
Code:
echo -n '\x23' | dd of=/dev/da0
dd: /dev/da0: Invalid argument

I'm trying to make some Linux code on FreeBSD.

Code:
if [ -n "$VTGPT" ]; then                                                                                                                                                                  
       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                                                                                                          
     else                                                                                                                                                                                         if [ -n "$VTGPT" ]; then                                                                                                                                                                  
       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                                                                                                          
     else                                                                                                                                                                                      
       xzcat ./boot/core.img.xz | dd status=none conv=fsync of=$DISK bs=512 count=2047 seek=1                                                                                                
     fi

Strangely I noticed that on FreeBSD bs=1 does not work. I needed to use bs=1B.


... sometime later.... don't know how I reached this conclusion... duh!
 
Since I can't get dd() to work, I thought I'd try to use sed() to change the input file before using dd(), but just to see if I can change hex value I'd try this

Bash:
sed -e 's/\x55AA/\x55BB/g' mbr > mbr-sed

but it doesn't make the change.

Can I actually use FreeBSD sed() to change hex chars?
 
Came across this suggestion


but it seems to require bash's 'ANSI-C Quoting' mechanism, whatever that is...
 
Code:
echo -n '\x23' | dd of=/dev/da0
dd: /dev/da0: Invalid argument
Makes sense. You can only write one block at a time.

I'm trying to make some Linux code on FreeBSD.
Do you know what that code is trying to do? What is the goal here? I could try to decode it myself and make educated guesses, but it's easier if you tell me what you want to accomplish.

Strangely I noticed that on FreeBSD bs=1 does not work. I needed to use bs=1B.
That changes the meaning of the dd statement. Except that if dd gets only a single byte on its input, even with bs=1B it will still write a short block, containing only one byte.
 
Code:
echo -n '\x23' | dd of=/dev/da0
dd: /dev/da0: Invalid argument

What shell are you using here?

That may work using bash's builtin echo (I don't use it, but I expect Ventoy does), but sh's echo -e doesn't do \x for hex strings. Try in sh(1):

$ echo -e "\0043\c" | hd
One byte result as ascii: |#|

Of course, far easier to use characters directly, given:

0x23 = \043 octal = '#' and
0x22 = \042 octal = |"| (doublequote)


I think consolidating these threads there would be good.
 
How do I copy a single character to a device?

This doesn't work:-

echo -n '\x22' | dd of=/dev/da0

Is this doable?
I'm a bit late to this thread and only want to comment on the use of "echo".
Using echo to produce characters other than human readable text is a bug waiting to happen. You enter the realm of SysV vs BSD madness when you use options such as echo -e or echo -n. That's why POSIX invented the printf(1) utility. It's available on BSD and Linux and Solaris and AIX and HP-UX and does exactly the same thing everywhere, while echo is a portability nightmare.
Please use printf '\x22\xAA\035%-10s!' "foo" for all your output needs and never look back.
 
Back
Top