如何在没有 uudecode、base64 或 x/y/z/ 调制解调器的情况下通过串口传输二进制文件?
Howto transfer a binary file over serial port without uudecode, base64, or x/y/z/ modem?
我正在尝试通过没有 uudecode、base64 或 x/y/z/调制解调器实用程序的小型嵌入式设备上的串行端口传输二进制文件。
我目前尝试的是:
$ sudo picocom -l -r -b 921600 --send-cmd "ascii-xfr -snv" /dev/ttyS0
# cat > libdebug.so
$ cat libdebug.so | sudo tee /dev/ttyS0
但这会挂起我的设备。
实际上,我能做的就是以ascii模式上传我自己的uudecode.sh,然后我可以用它来解码我自己的二进制文件!
这是在 ksh 上运行的脚本:
#!/bin/ksh
# uudecode in POSIX bourne shell
#
# *EXCRUCIATINGLY* SLOW!!!
#
# Taken from a reply to a blog post here:
# http://www.weeklywhinge.com/?p=108
#
# Copyright (c) 2015, Rafael Kitover <rkitover@gmail.com>
# Modified in 2018, Philippe Bouchard <philippeb8@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bs=0
while read -r t ; do
if [ "$bs" -eq 1 ] ; then
if [ "a$t" = "aend" ] ; then
bs=2
else
set $(printf "%d " "'$(echo $t | cut -c1)" "'$(echo $t | cut -c2)" "'$(echo $t | cut -c3)" "'$(echo $t | cut -c4)" "'$(echo $t | cut -c5)" "'$(echo $t | cut -c6)" "'$(echo $t | cut -c7)" "'$(echo $t | cut -c8)" "'$(echo $t | cut -c9)" "'$(echo $t | cut -c10)" "'$(echo $t | cut -c11)" "'$(echo $t | cut -c12)" "'$(echo $t | cut -c13)" "'$(echo $t | cut -c14)" "'$(echo $t | cut -c15)" "'$(echo $t | cut -c16)" "'$(echo $t | cut -c17)" "'$(echo $t | cut -c18)" "'$(echo $t | cut -c19)" "'$(echo $t | cut -c20)" "'$(echo $t | cut -c21)" "'$(echo $t | cut -c22)" "'$(echo $t | cut -c23)" "'$(echo $t | cut -c24)" "'$(echo $t | cut -c25)" "'$(echo $t | cut -c26)" "'$(echo $t | cut -c27)" "'$(echo $t | cut -c28)" "'$(echo $t | cut -c29)" "'$(echo $t | cut -c30)" "'$(echo $t | cut -c31)" "'$(echo $t | cut -c32)" "'$(echo $t | cut -c33)" "'$(echo $t | cut -c34)" "'$(echo $t | cut -c35)" "'$(echo $t | cut -c36)" "'$(echo $t | cut -c37)" "'$(echo $t | cut -c38)" "'$(echo $t | cut -c39)" "'$(echo $t | cut -c40)" "'$(echo $t | cut -c41)" "'$(echo $t | cut -c42)" "'$(echo $t | cut -c43)" "'$(echo $t | cut -c44)" "'$(echo $t | cut -c45)" "'$(echo $t | cut -c46)" "'$(echo $t | cut -c47)" "'$(echo $t | cut -c48)" "'$(echo $t | cut -c49)" "'$(echo $t | cut -c50)" "'$(echo $t | cut -c51)" "'$(echo $t | cut -c52)" "'$(echo $t | cut -c53)" "'$(echo $t | cut -c54)" "'$(echo $t | cut -c55)" "'$(echo $t | cut -c56)" "'$(echo $t | cut -c57)" "'$(echo $t | cut -c58)" "'$(echo $t | cut -c59)" "'$(echo $t | cut -c60)" "'$(echo $t | cut -c61)")
l=$(( -32 & 63 ))
shift
while [ $l -gt 0 ] ; do
i0=$(( -32 & 63))
shift
i1=$(( -32 & 63))
shift
i2=$(( -32 & 63))
shift
i3=$(( -32 & 63))
shift
if [ $l -gt 2 ] ; then
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))[=10=]$(($i1 >> 2 & 3))$(($i1 << 1 & 6 | $i2 >> 5))$(($i2 >> 2 & 7))[=10=]$(($i2 & 3))$(($i3 >> 3 & 7))$(($i3 & 7))"
true
elif [ $l -eq 2 ] ; then
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))[=10=]$(($i1 >> 2 & 3))$(($i1 << 1 & 6 | $i2 >> 5))$(($i2 >> 2 & 7))"
true
else
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))"
true
fi
l=$(($l-3))
done
fi
elif [ $(echo $t | cut -c1-5) = "begin" ]; then
bs=1
fi
done
然后就可以在设备上这样使用了:
# uudecode.sh < libdebug.so.uu > libdebug.so
编辑
显然 "printf" 甚至没有出现在我的设备上,但不用担心,因为 awk 中有一个更快的脚本可用:
#!/bin/sh
# uudecode in GNU awk (and some others, like OpenBSD) decodes stdin to stdout
#
# Copyright (c) 2014, Rafael Kitover <rkitover@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
awk=awk
if command -v gawk >/dev/null; then
awk=gawk
fi
$awk '
BEGIN {
charset=" !\"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_";
}
function charval(char) {
return index(charset, char) + 32 - 1;
}
/^begin / { next }
/^end$/ { exit }
{
cnt = substr([=12=], 1, 1);
if (cnt == "`") next;
cnt = charval(cnt) - 32;
enc = substr([=12=], 2, length([=12=]) - 1);
chars = 0;
pos = 1;
while (chars < cnt) {
grp = substr(enc, pos, 4);
gsub(/`/, " ", grp); # zero bytes
c1 = charval(substr(grp, 1, 1)) - 32;
c2 = charval(substr(grp, 2, 1)) - 32;
c3 = charval(substr(grp, 3, 1)) - 32;
c4 = charval(substr(grp, 4, 1)) - 32;
chars_bits = or(c4, or(or(lshift(c3, 6), lshift(c2, 12)), lshift(c1, 18)));
char[1] = sprintf("%c", rshift(and(chars_bits, 16711680), 16));
char[2] = sprintf("%c", rshift(and(chars_bits, 65280), 8));
char[3] = sprintf("%c", and(chars_bits, 255));
for (i = 1; i <= 3 && chars < cnt; i++) {
printf("%s", char[i]);
chars++;
}
pos += 4;
}
}
'
我正在尝试通过没有 uudecode、base64 或 x/y/z/调制解调器实用程序的小型嵌入式设备上的串行端口传输二进制文件。
我目前尝试的是:
$ sudo picocom -l -r -b 921600 --send-cmd "ascii-xfr -snv" /dev/ttyS0
# cat > libdebug.so
$ cat libdebug.so | sudo tee /dev/ttyS0
但这会挂起我的设备。
实际上,我能做的就是以ascii模式上传我自己的uudecode.sh,然后我可以用它来解码我自己的二进制文件!
这是在 ksh 上运行的脚本:
#!/bin/ksh
# uudecode in POSIX bourne shell
#
# *EXCRUCIATINGLY* SLOW!!!
#
# Taken from a reply to a blog post here:
# http://www.weeklywhinge.com/?p=108
#
# Copyright (c) 2015, Rafael Kitover <rkitover@gmail.com>
# Modified in 2018, Philippe Bouchard <philippeb8@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
bs=0
while read -r t ; do
if [ "$bs" -eq 1 ] ; then
if [ "a$t" = "aend" ] ; then
bs=2
else
set $(printf "%d " "'$(echo $t | cut -c1)" "'$(echo $t | cut -c2)" "'$(echo $t | cut -c3)" "'$(echo $t | cut -c4)" "'$(echo $t | cut -c5)" "'$(echo $t | cut -c6)" "'$(echo $t | cut -c7)" "'$(echo $t | cut -c8)" "'$(echo $t | cut -c9)" "'$(echo $t | cut -c10)" "'$(echo $t | cut -c11)" "'$(echo $t | cut -c12)" "'$(echo $t | cut -c13)" "'$(echo $t | cut -c14)" "'$(echo $t | cut -c15)" "'$(echo $t | cut -c16)" "'$(echo $t | cut -c17)" "'$(echo $t | cut -c18)" "'$(echo $t | cut -c19)" "'$(echo $t | cut -c20)" "'$(echo $t | cut -c21)" "'$(echo $t | cut -c22)" "'$(echo $t | cut -c23)" "'$(echo $t | cut -c24)" "'$(echo $t | cut -c25)" "'$(echo $t | cut -c26)" "'$(echo $t | cut -c27)" "'$(echo $t | cut -c28)" "'$(echo $t | cut -c29)" "'$(echo $t | cut -c30)" "'$(echo $t | cut -c31)" "'$(echo $t | cut -c32)" "'$(echo $t | cut -c33)" "'$(echo $t | cut -c34)" "'$(echo $t | cut -c35)" "'$(echo $t | cut -c36)" "'$(echo $t | cut -c37)" "'$(echo $t | cut -c38)" "'$(echo $t | cut -c39)" "'$(echo $t | cut -c40)" "'$(echo $t | cut -c41)" "'$(echo $t | cut -c42)" "'$(echo $t | cut -c43)" "'$(echo $t | cut -c44)" "'$(echo $t | cut -c45)" "'$(echo $t | cut -c46)" "'$(echo $t | cut -c47)" "'$(echo $t | cut -c48)" "'$(echo $t | cut -c49)" "'$(echo $t | cut -c50)" "'$(echo $t | cut -c51)" "'$(echo $t | cut -c52)" "'$(echo $t | cut -c53)" "'$(echo $t | cut -c54)" "'$(echo $t | cut -c55)" "'$(echo $t | cut -c56)" "'$(echo $t | cut -c57)" "'$(echo $t | cut -c58)" "'$(echo $t | cut -c59)" "'$(echo $t | cut -c60)" "'$(echo $t | cut -c61)")
l=$(( -32 & 63 ))
shift
while [ $l -gt 0 ] ; do
i0=$(( -32 & 63))
shift
i1=$(( -32 & 63))
shift
i2=$(( -32 & 63))
shift
i3=$(( -32 & 63))
shift
if [ $l -gt 2 ] ; then
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))[=10=]$(($i1 >> 2 & 3))$(($i1 << 1 & 6 | $i2 >> 5))$(($i2 >> 2 & 7))[=10=]$(($i2 & 3))$(($i3 >> 3 & 7))$(($i3 & 7))"
true
elif [ $l -eq 2 ] ; then
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))[=10=]$(($i1 >> 2 & 3))$(($i1 << 1 & 6 | $i2 >> 5))$(($i2 >> 2 & 7))"
true
else
echo -ne "[=10=]$(($i0 >> 4))$(($i0 >> 1 & 7))$(($i0 << 2 & 4 | $i1 >> 4))"
true
fi
l=$(($l-3))
done
fi
elif [ $(echo $t | cut -c1-5) = "begin" ]; then
bs=1
fi
done
然后就可以在设备上这样使用了:
# uudecode.sh < libdebug.so.uu > libdebug.so
编辑
显然 "printf" 甚至没有出现在我的设备上,但不用担心,因为 awk 中有一个更快的脚本可用:
#!/bin/sh
# uudecode in GNU awk (and some others, like OpenBSD) decodes stdin to stdout
#
# Copyright (c) 2014, Rafael Kitover <rkitover@gmail.com>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
awk=awk
if command -v gawk >/dev/null; then
awk=gawk
fi
$awk '
BEGIN {
charset=" !\"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_";
}
function charval(char) {
return index(charset, char) + 32 - 1;
}
/^begin / { next }
/^end$/ { exit }
{
cnt = substr([=12=], 1, 1);
if (cnt == "`") next;
cnt = charval(cnt) - 32;
enc = substr([=12=], 2, length([=12=]) - 1);
chars = 0;
pos = 1;
while (chars < cnt) {
grp = substr(enc, pos, 4);
gsub(/`/, " ", grp); # zero bytes
c1 = charval(substr(grp, 1, 1)) - 32;
c2 = charval(substr(grp, 2, 1)) - 32;
c3 = charval(substr(grp, 3, 1)) - 32;
c4 = charval(substr(grp, 4, 1)) - 32;
chars_bits = or(c4, or(or(lshift(c3, 6), lshift(c2, 12)), lshift(c1, 18)));
char[1] = sprintf("%c", rshift(and(chars_bits, 16711680), 16));
char[2] = sprintf("%c", rshift(and(chars_bits, 65280), 8));
char[3] = sprintf("%c", and(chars_bits, 255));
for (i = 1; i <= 3 && chars < cnt; i++) {
printf("%s", char[i]);
chars++;
}
pos += 4;
}
}
'