The write() syscall may be interrupted. Handle EINTR and retry it.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
This delay is not needed anymore since kwboot already handles retrying
logic for incomplete xmodem packets and also forces BootROM to flush its
input queue. Removing it decreases total transfer time.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Force the BootROM to flush its input queue after sending boot pattern.
This ensures that after function kwboot_bootmsg() finishes, BootROM is
able to start receiving xmodem packets without any specific delay or
setup.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Allow option -b without image path parameter, to send boot pattern and
wait for response but not send any image. This allows to use kwboot just
for processing boot pattern and user can use any other xmodem tool for
transferring the image itself (e.g. sx). Useful for debugging purposes.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
When kwboot is unable to resend current xmodem packet, show an 'E' in the
progress output instead of a '+'. This allows to distinguish between the
state when kwboot is retrying sending the packet and when retry is not
possible.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Unfortunately during some stages of xmodem transfer, A385 BootROM is not
able to handle repeated xmodem packets. So if an error occurs during that
stage, stop the transfer and return failure.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Marvell BootROM expects retransmission of previous xmodem packet only in
the case when it sends NAK response to the host.
Do not change non-xmodem response (possibly UART transfer error) to NAK
in kwboot_xm_recv_reply() function. Allow caller to receive original
response from device.
Change argument 'nak_on_non_xm' to 'stop_on_non_xm'. Instead of changing
non-xmodem character to NAK, stop processing on invalid character and
return it.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
It is unknown why handling of CAN byte was added into kwboot tool as
Marvell BootROM does not support CAN byte. It never sends CAN byte to host
and if host sends CAN byte BootROM handles it as an unknown byte.
Remove code for handling and sending CAN bytes from the kwboot tool.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Sometimes if the first byte of xmodem packet (SOH) is incorrectly
transmitted, BootROM sends NAK for every non-SOH received byte, which
makes BootROM and the host kwboot tool out of sync. BootROM automatically
re-synchronizes after 2s pause by dropping its input queue. So when
attempting retransmit for 9th time or later, ignore NAK reply from BootROM
and either wait for valid ACK or let kwboot timeout, which implies
re-synchronization.
This fixes retransmission of xmodem packets and allows kwboot to work also
without "Waiting ... and flushing tty" code which is at the beginning of
kwboot xmodem transfer.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Use the blk_rsp_timeo variable when sleeping before flushing tty.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Fix xmodem retry mechanism if some bytes from xmodem packet were lost and
BootROM is still waiting for completing previous xmodem packet.
It is required to wait at least 1.312s on A385, otherwise BootROM does not
accept next xmodem packet if previous one was not completely transferred.
2s should be enough timeout cause that BootROM will drop incomplete xmodem
packet and expects new packet.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Despite the official specification, BootROM does not look at the lowest bit
of ext field but rather checks if ext field is non-zero.
Moreover original Marvell doimage tool puts into the mhdr->ext field the
number of extended headers, so basically it sets ext filed to non-zero
value if some extended header is present.
Fix U-Boot dumpimage and kwboot tools to parse correctly also kwbimage
files created by Marvell doimage tool, in the same way as the BootROM is
doing it when booting these images.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
It is useful to see kwboot version in the boot log output for debugging
purposes.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
Properly calculate and align image header size to xmodem block size.
Kirkwood v0 images do not have stored total size of header in header
structure itself like it is for v1 images. So kwbheader_size() calculates
size by traversing image structure itself. Aligning is done in kwboot by
putting zero padding bytes between the header and data part.
Signed-off-by: Pali Rohár <pali@kernel.org>
Tested-by: Tony Dinh <mibodhi@gmail.com>
Reviewed-by: Stefan Roese <sr@denx.de>
After successful transfer of whole image only two things can happen:
- BootROM starts execution of data block, which changes UART baudrate
back to 115200 Bd,
- board crashes and causes CPU reset
In both cases UART baudrate is reset to the default speed. So there is
no need to send special magic sequence to inform kwboot that baudrate is
going to be reset and kwboot does not need to wait for this event and
can do it immediately after BootROM acknowledges end of xmodem transfer.
Move ARM code for sending magic sequence from main baudrate change
section to binhdr_pre section which is executed only before changing
baudrate from the default value of 115200 Bd to some new value. Remove
kwboot code waiting for magic sequence after successful xmodem transfer.
Rationale: sometimes when using very high UART speeds, magic sequence is
damaged and kwboot fails at this last stage. Removal of this magic
sequence makes booting more stable.
Data transfer protocol (xmodem) is using checksums and retransmit, so it
already deals with possible errors on transfer line.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
The ARM code we inject into the image to change baudrate back to the
default value of 115200 Baud, which is run after successful UART transfer
of the whole image, cannot use stack as at this stage stack pointer is not
initialized yet.
Stack can only be used when BootROM is executing binary header, to
preserve state of registers, since BootROM expects that.
Change the ARM baudrate code to not use stack at all and put binary
header specific pre + post code (which stores and restores registers) into
separate arrays.
The baudrate change code now jumps at it's end and expects that there is
either code which returns to the BootROM or jumps to the original exec
address.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Older Armada SoCs have custom ARMv5te compatible core which does not
support movt instruction. So replace mov + movt instruction pair used for
immediate move construction by mov + orr instructions which are supported
also by ARMv5te.
After this change kwboot ARM code should be compatible with any 32-bit ARM
core compatible by ARMv2 or new. At least GNU AS does not throw any error
or warning.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Increase loop cycles from 600000 to 2998272, which should increase delay
from 1ms to about 5ms on 1200 MHz CPU.
The Number 2998272 was chosen as the nearest value around 3000000 which can
be encoded into one ARM mov instruction. It avoids usage of movt instruction
which is not supported by ARMv5te cores.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Kwboot puts each xmodem packet to kernel queue, then waits until all bytes
of that packet are transmitted over UART and then waits for xmodem reply
until it is received into kernel queue.
If some reply is received during the time we are waiting until all bytes
are transmitted, then kernel puts them into the queue and returns it to
kwboot in next read() call.
So there is no need to wait (with tcdrain() function) until all bytes from
xmodem packet are transmitted over UART, since any reply received either
during that time or after is returned to kwboot with the next read().
Therefore do not call tcdrain() after each xmodem packet sent. Instead
directly wait for any reply after putting xmodem packet into write kernel
queue.
This change could speed up xmodem transfer in case tcdrain() function waits
for a longer time.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
After the trasfer of last header packet, it is possible that baudrate
change pattern is received, and also that NAK byte is received so that
the packet should be sent again.
Thus we should not clear the baudrate change state when sending retry
of that packet.
Move code for initializing state variables from kwboot_xm_recv_reply()
to kwboot_xm_sendblock().
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Currently when kwboot receive some garbage reply which does not understand,
it waits 1s before it tries to resend packet again.
The most common error on UART is that receiver sees some bit flipped which
results in invalid reply.
This behavior slows down xmodem transfer over UART as basically on every
error kwboot is waiting one second.
To fix this, try to resend xmodem packet for first 3 attempts immediately
without any delay. If broken reply is received also after the 3 attempts,
continue retrying with 1s delay like it was before.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
This patch does not change behavior of the code, just allows to implement
new changes more easily.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Size of the header stored in kwbimage may be larger than real used size in
the kwbimage header. If there is unused space in kwbimage header then use
it for growing it. So update code to calculate used space of kwbimage
header.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
This ensures that kwboot_img_grow_hdr() function still sees valid kwbimage
header.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Expression (hdrsz % KWBOOT_XM_BLKSZ) is non-zero therefore expression
(KWBOOT_XM_BLKSZ - hdrsz % KWBOOT_XM_BLKSZ) is always less than value
KWBOOT_XM_BLKSZ. So there is no need to add another modulo. Also rename
variable `offset` to `grow` which better describes what is stored in
this variable.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
It is hard to debug why kwboot is failing when the last message is
'Finishing transfer' and no additional output. So show verbose message when
kwboot finished transfer and is waiting for baudrate change magic sequence.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
For kwbimage v1, tell BootROM to send BootROM messages to UART port number
0 (used also for UART booting) with default baudrate (which should be
115200) and do not touch UART MPP configuration.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
If data part of image is modified, update 4-byte data checksum.
It looks like A385 BootROM does not verify this checksum for image
loaded via UART, but we do not know if other BootROMs are also ignoring
it. It is always better to provide correct checksum.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Some vendor U-Boot kwbimage binaries (e.g. those for A375) have load
address set to zero. Therefore it is not possible to inject code which
changes baudrate back to 115200 Bd before the data part.
So instead inject it after the data part and change kwbimage execution
address to that offset. Also store original execution address into
baudrate change code, so after it changes baudrate back to 115200 Bd, it
can jump to orignal address.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Data part of the image contains 4-byte checksum. Validate it when
processing the image.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
SPI image header and data parts do not have to be aligned to 128 byte
xmodem block size. So reserve additional memory for aligning header part
and additional memory for aligning data part.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Explicitly disable 2 stop bits by clearing CSTOPB flag, disable modem
control flow by clearing CRTSCTS flag and do not send hangup after closing
device by clearing HUPCL flag.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Explicitly zero out the rfds fd_set with FD_ZERO() before using it.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
kwbimage v1 has also nandpagesize field. So set it to zero for both image
versions when image is not signed.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
ARM executable code inside the BIN header on some mvebu platforms
(e.g. A370, AXP) must always be aligned with the 128-bit boundary. This
requirement can be met by inserting dummy arguments into BIN header.
Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
Add Pali and Marek as another authors of the kwboot utility.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Change kwboot_img_patch() to avoid code repetition of setting errno to
EINVAL.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
The kwboot utility does not handle EAGAIN / EBUSY errors, it expects
blocking mode on tty - it uses select() to check if data is available.
Disable non-blocking mode by clearing O_NDELAY flag which was set by
open().
We can't just take O_NDELAY from open(), because it is required there
until the CLOCAL flag is set on the tty.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Function kwboot_tty_recv() has its own handling of read timeout, we
don't need to do set it in tty settings.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Retrieve current terminal settings via tcgetattr(), set to raw mode with
cfmakeraw(), enable receiver via CREAD and ignore modem control lines
via CLOCAL.
Signed-off-by: Pali Rohár <pali@kernel.org>
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
The tcsetattr() function can return 0 even if baudrate was not changed.
Check whether baudrate was changed to requested value, and in case of
arbitrary baudrate, check whether the set value is within 3% tolerance.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
The A38x platform supports more baudrates than just those defined by the
Bn constants, and some of them are higher than the highest Bn baudrate
(the highest is 4 MBd while A38x support 5.15 MBd).
On Linux, add support for arbitrary baudrates. (Since there is no
standard POSIX API to specify arbitrary baudrate for a tty device, this
change is Linux-specific.)
We need to use raw TCGETS2/TCSETS2 or TCGETS/TCSETS ioctls with the
BOTHER flag in struct termios2/termios, defined in Linux headers
<asm/ioctls.h> (included by <sys/ioctl.h>) and <asm/termbits.h>. Since
these headers conflict with glibc's header file <termios.h>, it is not
possible to use libc's termios functions and we need to reimplement them
via ioctl() calls.
Note that the Bnnn constants from <termios.h> need not be compatible
with Bnnn constants from <asm/termbits.h>.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ termios macros rewritten to static inline functions (for type control)
and moved to tools/termios_linux.h ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Add support for uploading the boot image (the data part only) at higher
baudrate than the standard one.
The kwboot utility already has -B option, but choosing other baudrate
than the standard one (115200 Bd) can only work for debug mode, not for
booting the device. The BootROM for kwboot supported platforms (Orion,
Kirkwood, Dove, Discovery, AXP, A37x, A38x, A39x) cannot change the
baudrate when uploading boot image via the Xmodem protocol, nor can it
be configured via strapping pins.
So instead we add this support by injecting baudrate changing code into
the kwbimage v1 header as a new optional binary extension. This code is
executed by BootROM after it receives the whole header. The code sends
the magic string "$baudratechange\0" just before changing the baudrate
to let kwboot know that it should also change it. This is because the
injected code is run as the last binary extension, and we do not want
to loose possible output from other possible binary extensions that
came before it (in most cases this is U-Boot SPL).
We also inject the code before the payload (the data part of the image),
to change the baudrate back to the standard value, in case the payload
does not reset UART.
This change improves boot time via UART significantly (depending on the
chosen baudrate), which is very useful when debugging.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ major refactor ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Explicitly check the image size against size of struct main_hdr_v1.
This way the check is more readable, since the `hdrsz` variable
may semantically contain another value.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
The beginning of image data must be sent in a separate xmodem block;
the block must not contain end of header with the beginning of data.
Therefore we need to ensure that the image header size is a multiple of
xmodem block size (which is 128 B).
Read the file into a malloc()ed buffer of enough size instead of
mmap()ing it. (If we are going to move the data, most of the pages will
be dirty anyway.) Then move the payload if header size needs to be
increased.
Signed-off-by: Pali Rohár <pali@kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Add functions kwbheader_size() and kwbheader_size_for_csum().
Refactor code determining header size to use these functions.
Refactor header checksum determining function.
Remove stuff that is not needed anymore.
This simplifies the code a little and fixes one instance of validating
header size meant for checksum instead of whole header size.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
Rename this function to kwbimage_version() and don't cast argument if
not needed.
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>
SPI/NOR kwbimage may have destination address set to 0xFFFFFFFF, which
means that the image is not downloaded to DDR but rather it is executed
directly from SPI/NOR. In this case execution address is set to SPI/NOR
area.
When patching image to UART type, change destination and execution
addresses from SPI/NOR XIP area to DDR area 0x00800000 (which is default
for A38x).
Signed-off-by: Pali Rohár <pali@kernel.org>
[ refactored ]
Signed-off-by: Marek Behún <marek.behun@nic.cz>
Reviewed-by: Stefan Roese <sr@denx.de>