-
Notifications
You must be signed in to change notification settings - Fork 1
Protocols
Protocols are described as a name and a set of functions:
typedef struct up_protocol_struct {
const char *name;
void *(*init)(void);
int (*prepare)(void *h, up_context_t *ctx, up_load_arg_t *arg);
int (*transfer)(void *h, up_context_t *ctx, up_load_arg_t *arg, const uint8_t *buf, int buf_bytes);
int (*complete)(void *h, up_context_t *ctx, up_load_arg_t *arg);
int (*shutdown)(void *h, up_context_t *ctx);
} up_protocol_t;
A new protocol is added to the system by inserting its descriptor into the array of descriptors used for command-line parsing by the front-end.
The name
field identifies the protocol to the user, and is used in command-line parsing.
A protocol's init
function is called at the start of the program to do any global initialisation. It returns the handle to be passed to all future function calls for this protocol. A return value of NULL
indicates an error; successful initialisation functions must return a non-NULL value, even if it's only (void *)1
.
The prepare
entry point is called at the start of a boot stage. This is traditionally the point where the baud rate is changed, and the utility function utils_protocol_set_baud()
has the right signature to be used directly as the prepare
function if appropriate. Otherwise the protocol should do any other preparation before downloading a file here. Aside from changing the baud rate, communications with the back-end should be avoided; users may need to do some work before the upload can take place, for example by stopping uboot
before its automation cuts in. The function should return 0 on success, or a negative number on error.
The transfer
entry point is called by the core logic to do the actual file transfer. The file to transfer will already be open, and its file descriptor will be held in the fd
field of the boot state arg
parameter passed in. As well as the protocol handle, the system context and the boot stage parameter, the transfer function is given a byte buffer containing any bytes that the core system has read from the back-end. These bytes have already been written to the console and logged.
The transfer
function should return a negative number on error, a positive number if the upload completed, and zero if the upload has not yet started or is still ongoing. It should periodically call utils_check_critical_control()
to allow keyboard interrupts.
The complete
entry point is called once transfer is complete, and may be required to undo the work of the prepare
function. It should return zero on success or a negative number on error.
Finally, the shutdown
entry point is called at the end of the program to release any resource protocol initialisation claimed. It should return zero on success or a negative number on error.
All function entries except for transfer
may be NULL if the protocol does not need to do anything at that stage. The transfer
entry may only be NULL if there is no file to transfer, which only is only the case when upc2 has switched into console mode after all transfers are complete.
Procotol handler functions should only talk to the back-end using the up_bio_t
object in the system context, for example through ctx->bio->write()
or ctx->bio->safe_write()
.
Protocol handler functions should use the file descriptor ctx->ttyfd
to communicate with the console. Future versions may allow for dynamically redirecting console input and output, and using ctx->ttyfd
proofs the code against that. The utility function utils_safe_printf()
already does this. Error messages should of course be written to stderr as usual.
upc2 currently supports two upload protocols: grouch and xmodem.
Grouch is a very simple upload protocol that has been used in-house for years. It goes like this:
- The target system sends the six characters
*LOAD*
to indicate that it is ready to upload. - The host system (upc2) sends a
*
character for synchronisation. - The host system sends the image length in bytes as a four byte quantity, big-endian.
- The host system sends the image.
- The host system sends a four byte checksum, big-endian.
The checksum is the sum of the bytes of the image only, i.e. not including the initial *
and image length.
upc2 handles XMODEM and XMODEM/CRC. For more details on the protocol, see the XMODEM/YMODEM reference at http://pauillac.inria.fr/~doligez/zmodem/ymodem.txt