wire_format — Wire format

This module describes the “wire” format used to communicate between the user space tools and the punchboot bootloader.


Source code: include/pb-tools/wire.h, lib/wire.c


Punch BOOT

Copyright (C) 2020 Jonas Blixt jonpe960@gmail.com

SPDX-License-Identifier: BSD-3-Clause

This file contains the ‘wire’ format for the punchboot bootloader. The various structs and defines are used for sending data between host and device.

Generally a struct pb_command is sent from the host and the device is expected to respond with a struct pb_result.

Additional read/writes are optional but must always be terminated by sending a struct pb_result

The pb_commands enum encodes all of the available commands.

Defines

PB_WIRE_MAGIC

Magic number present in all the command and result headers.

PB_COMMAND_REQUEST_MAX_SIZE

Maximum number of bytes that can be embedded in a command request

PB_RESULT_RESPONSE_MAX_SIZE

Maximum number of bytes that can be embedded in a response result

PB_WIRE_PART_FLAG_BOOTABLE

The partition is bootable

PB_WIRE_PART_FLAG_OTP

The partition can only be written once

PB_WIRE_PART_FLAG_WRITABLE

The partition is writeable

PB_WIRE_PART_FLAG_ERASE_BEFORE_WRITE

The partition must be erased before any write operation

Enums

enum pb_auth_method

The punchboot protocol support two different methods of authentication. The device may choose to implement more then one.

Values:

enumerator PB_AUTH_INVALID

Invalid, guard

enumerator PB_AUTH_ASYM_TOKEN

Use a signature based authentication token

enumerator PB_AUTH_PASSWORD

Use a password based authentication

enum pb_commands

Punchboot commands

Values:

enumerator PB_CMD_INVALID
enumerator PB_CMD_DEVICE_RESET
enumerator PB_CMD_DEVICE_IDENTIFIER_READ
enumerator PB_CMD_DEVICE_READ_CAPS
enumerator PB_CMD_SLC_SET_CONFIGURATION
enumerator PB_CMD_SLC_SET_CONFIGURATION_LOCK
enumerator PB_CMD_SLC_SET_EOL
enumerator PB_CMD_SLC_REVOKE_KEY
enumerator PB_CMD_SLC_READ
enumerator PB_CMD_BOOTLOADER_VERSION_READ
enumerator PB_CMD_PART_TBL_READ
enumerator PB_CMD_PART_TBL_INSTALL
enumerator PB_CMD_PART_VERIFY
enumerator PB_CMD_PART_ACTIVATE
enumerator PB_CMD_PART_BPAK_READ
enumerator PB_CMD_PART_ERASE
enumerator PB_CMD_AUTHENTICATE
enumerator PB_CMD_AUTH_SET_OTP_PASSWORD
enumerator PB_CMD_STREAM_INITIALIZE
enumerator PB_CMD_STREAM_PREPARE_BUFFER
enumerator PB_CMD_STREAM_WRITE_BUFFER
enumerator PB_CMD_STREAM_FINALIZE
enumerator PB_CMD_BOOT_PART
enumerator PB_CMD_BOOT_RAM
enumerator PB_CMD_BOARD_COMMAND
enumerator PB_CMD_BOARD_STATUS_READ
enumerator PB_CMD_STREAM_READ_BUFFER
enumerator PB_CMD_PART_RESIZE
enumerator PB_CMD_BOOT_STATUS
enumerator PB_CMD_END
enum pb_slc

Values:

enumerator PB_SLC_INVALID
enumerator PB_SLC_NOT_CONFIGURED
enumerator PB_SLC_CONFIGURATION
enumerator PB_SLC_CONFIGURATION_LOCKED
enumerator PB_SLC_EOL

Functions

int pb_wire_init_command(struct pb_command *command, enum pb_commands command_code)

Initializes and resets a command structure. The magic value is populated and the command code is set.

Parameters
  • command[out] Pointer to a command structure

  • command_code[in] The actual command code

Returns

PB_RESULT_OK on success or a negative number on errors

int pb_wire_init_command2(struct pb_command *command, enum pb_commands command_code, void *data, size_t size)

Initializes and resets a command structure. The magic value is populated, the command code is set and the request array is populated with data.

Parameters
  • command[out] Pointer to a command structure

  • command_code[in] The actual command code

  • data[in] Pointer to data that will be stored in the request array

  • size[in] Number of bytes of data

Returns

PB_RESULT_OK on success or a negative number on errors

int pb_wire_init_result(struct pb_result *result, enum pb_results result_code)

Initializes and resets a result structure. The magic value is populated and the result code is set.

Parameters
  • result[out] pointer to a pb_result structure

  • result_code[in] The result code

Returns

PB_RESULT_OK on success or a negative number on errors

int pb_wire_init_result2(struct pb_result *result, enum pb_results result_code, void *data, size_t size)

Initializes and resets a result structure. The magic value is populated and the result code is set.

Parameters
  • result[out] pointer to a pb_result structure

  • result_code[in] The result code

  • data[in] Pointer to data that will be stored in the response array

  • size[in] size in bytes of the data

Returns

PB_RESULT_OK on success or a negative number on errors

bool pb_wire_valid_command(struct pb_command *command)

Checks that a command is valid and contains the correct magic number

Parameters

command[in] The command to check

Returns

True on if the command is valid or false if not

bool pb_wire_valid_result(struct pb_result *result)

Checks that a result is valid and contains the correct magic number

Parameters

result[in] The result to check

Returns

True on if the result is valid or false if not

bool pb_wire_requires_auth(struct pb_command *command)

Checks if a command requires the user to authenticate before issuing the command.

Parameters

command[in] The command to check

Returns

True if the command requires an authenticated session

const char *pb_wire_command_string(enum pb_commands cmd)

Translates a punchboot command to a textual representation

Parameters

cmd[in] The command

Returns

a string or “”

const char *pb_wire_slc_string(enum pb_slc slc)

Translates a punchboot security life cycle value to a string

Parameters

slc[in] SLC value

Returns

a string or “”

struct pb_command
#include <wire.h>

Punchboot command structure (64 bytes)

Alignment: 64 bytes

Public Members

uint32_t magic

PB wire format magic, set to ‘PBL0’ and changed for breaking changes in the protocol

uint8_t command

Command to be executed, from enum pb_commands

uint8_t rz[3]

Reserved

uint8_t request[PB_COMMAND_REQUEST_MAX_SIZE]
struct pb_result
#include <wire.h>

Punchboot command result (64 bytes)

Alignment: 64 Bytes

Public Members

uint32_t magic

PB wire format magic

int8_t result_code

Command result code

uint8_t rz[3]

Reserved

uint8_t response[PB_RESULT_RESPONSE_MAX_SIZE]

Response data

struct pb_result_device_caps
#include <wire.h>

Device capabilities

Public Members

uint8_t stream_no_of_buffers

Number of stream buffers

uint32_t stream_buffer_size

Size of stream buffers in bytes

uint16_t operation_timeout_ms

Generic operation timeout

uint16_t part_erase_timeout_ms

Maximum erase time for a partition

uint8_t bpak_stream_support

Set to 1 if the device supports receiving concatenated bpak archives

uint32_t chunk_transfer_max_bytes

Maximum number of bytes in one transfer

uint8_t rz[18]

Reserved

struct pb_result_part_table_read
#include <wire.h>

Read partition table response

Public Members

uint8_t no_of_entries

Number of partitions in the following data

uint8_t rz[31]

Reserved

struct pb_result_part_table_entry

Public Members

uint8_t uuid[16]

Partition UUID

char description[37]

Textual description of partition

uint64_t first_block

Partition start block

uint64_t last_block

Last(inclusive) block of partition

uint16_t block_size

Block size

uint8_t flags

Flags

uint8_t rz[56]

Reserved

struct pb_command_stream_initialize
#include <wire.h>

Initialize streaming to or from a partition

Public Members

uint8_t part_uuid[16]

Partition UUID

uint8_t rz[16]

Reserved

struct pb_command_stream_prepare_buffer
#include <wire.h>

Prepare buffer to receive data

This command must always be followd by a data transfer corresponding the size field.

Public Members

uint32_t size

Bytes to transfer into buffer

uint8_t id

Buffer ID

uint8_t rz[27]

Reserved

struct pb_command_stream_write_buffer
#include <wire.h>

Write data from an internal buffer to a partition

Public Members

uint32_t size

Bytes to transfer from buffer to partition

uint64_t offset

Offset in bytes into the partition

uint8_t buffer_id

Source buffer id

uint8_t rz[19]

Reserved

struct pb_command_stream_read_buffer
#include <wire.h>

Read data from a partition to an internal buffer

This command does not need a prepare_buffer CMD before it.

Public Members

uint32_t size

Bytes to transfer from partition to buffer

uint64_t offset

Offset in bytes into the partition

uint8_t buffer_id

Source buffer id

uint8_t rz[19]

Reserved

struct pb_command_authenticate
#include <wire.h>

Authentication command

The authentication command must be followed by a write opertion by the host that contains the authentication data.

Public Members

uint8_t method

Method to use for authenticaton see enum pb_auth_method

uint16_t size

Authentication data size in bytes

uint32_t key_id

Optional key id for token based auth

uint8_t rz[25]

Reserved

struct pb_command_verify_part
#include <wire.h>

Verify partition

The device computes a sha256 hash and compares with the input hash

Public Members

uint8_t uuid[16]

UUID of partition to verify

uint8_t sha256[32]

Expected sha256 hash

uint32_t size

Size in bytes

uint8_t bpak

Parse bpak header

uint8_t rz[2]

Reserved

struct pb_command_activate_part
#include <wire.h>

Activate bootable partition command

Public Members

uint8_t uuid[16]

UUID of partition to activate

uint8_t rz[16]

Reserved

struct pb_command_read_bpak
#include <wire.h>

Read BPAK header command

If the last 4kByte of the partition contains a valid bpak header the header is sent to the host using this command.

Public Members

uint8_t uuid[16]

Partition UUID

uint8_t rz[16]

Reserved

struct pb_command_erase_part
#include <wire.h>

Erase partition command

Public Members

uint8_t uuid[16]

UUID of partition to erase

uint8_t rz[16]

Reserved

struct pb_command_resize_part
#include <wire.h>

Resize partition command

Public Members

uint8_t uuid[16]

UUID of partition to erase

size_t blocks

Size in 512byte blocks

uint8_t rz[8]

Reserved

struct pb_command_install_part_table
#include <wire.h>

Install default partition table

Public Members

uint8_t uu[16]
uint8_t variant
struct pb_result_device_identifier
#include <wire.h>

Read device identifier

Public Members

uint8_t device_uuid[16]

Device UUID

char board_id[16]

Board id string

uint8_t rz[23]

Reserved

struct pb_result_slc
#include <wire.h>

Security Life Cycle (SLC) result

Public Members

uint8_t slc

SLC state

uint8_t rz[31]

Reserved

struct pb_result_slc_key_status
#include <wire.h>

Active/Revoked keys result

Public Members

uint32_t active[16]

ID’s of keys that are active

uint32_t revoked[16]

ID’s of keys that are revoked

struct pb_command_revoke_key
#include <wire.h>

Revoke key command

Public Members

uint32_t key_id

ID of key to revoke

uint8_t rz[28]

Reserved

struct pb_command_boot_part
#include <wire.h>

Boot from partition command

Public Members

uint8_t uuid[16]

UUID of bootable partition

uint8_t verbose

Verbose boot output

uint8_t rz[15]

Reserved

struct pb_command_ram_boot
#include <wire.h>

Ram boot command

A bpak image is transfered to ram and executed

Public Members

uint8_t verbose

Verbose boot output

uint8_t uuid[16]

Make it look like we are booting this part

uint8_t rz[15]

Reserved

struct pb_command_board
#include <wire.h>

Board specific command

This optional command, when called will run a function in the board module that can be unique for a board.

Public Members

uint32_t command

Board command to run

uint32_t request_size

Request size in bytes

uint32_t response_buffer_size

Maximum amount of data that can be included in the response

uint8_t rz[20]

Reserved

struct pb_result_board
#include <wire.h>

The result structure for the board command

Public Members

uint32_t size

Bytes to read after the result structure

uint8_t rz[28]

Reserved

struct pb_result_board_status
#include <wire.h>

Board status result

Public Members

uint32_t size

Bytes to read after the result structure

uint8_t rz[28]

Reserved

struct pb_result_boot_status
#include <wire.h>

Boot status result

Public Members

uint8_t uuid[16]

Active boot partition

char status[16]

Optional, textual status message