Home ·

- Getting started with SAM-BA on SAM9X60 devices

# Getting started with SAM-BA on SAM9X60 devices

## Connecting to the SAM-BA monitor

For USB connection, the host running sam-ba should be connected to the USB device port of the SAM9X60 board design. On SAM9X60-EK boards, this port is labeled USBA (J7).

The USB device port must not be confused with other USB connectors such as VBUS_JLINK (J22)

## Predefined boards and customer board designs

The sam-ba program comes with a predefined sam9x60-ek board that sets default values for different settings such as the applet console or memory controller instances and iosets.

This predefined board can be selected with the -b sam9x60-ek option on the sam-ba command line.

However the -d sam9x60 option should be used instead on customer board designs not to load any default settings. Instead, additional parameters may be passed to the -d sam9x60:<console_instance>:<console_ioset> option to select the applet console. The applet console, when enabled, is used by any applet to print its traces.

Also, default memory controller settings, if any, can be overridden too passing additionnal arguments to the -a <applet> option for the applet mananing the memory controller.

## Supported applets

The list of supported applets can be displayed with the following command:

    $ sam-ba -p serial -d sam9x60 -a help
    Known applets: bootconfig, lowlevel, extram, sdmmc, serialflash, qspiflash, nandflash, reset, readuniqueid

Applet | Short description | Examples
--- | --- | ---
bootconfig | Manage boot configuration of the device, select boot media | Programming a Boot Configuration packet
extram | Initialize the external RAM (not needed by any other applets) |
lowlevel | Setup the clock tree (only needed by the extram applet)
nandflash | Manage raw NAND flash memories connected to the EBI and driven by the SMC | Programming a raw NAND flash
pairingmode | Translate a bootstrap master image into a bootstrap paired image |
qspiflash | Manage (Q)SPI NOR flash memories connected to the QSPI controller | Programming a QSPI NOR flash
readuniqueid | Read the device unique ID |
reset | Reset the target device
sdmmc | Manage e.MMC and SD Cards connected to some SDMMC instance | Programming a SD Card or e.MMC
serialflash | Manage (Q)SPI NOR flash memories connected to some FLEXCOM SPI instance | Programming a SPI NOR flash

## OTPC Emulation mode

During developments and tests, we recommend the user to enable the OTPC emulation mode. Doing so, the OTPC controller replaces its OTP matrix by SRAM1 to store all user area packets, including the Boot Configuration packet, the Secure Boot Configuration packet and the User Hardware Configuration packet.

The bootconfig applet provides the user with helper commands to manage the OTPC emulation mode.

As SRAM1 is powered by VDDBU, data are kept after reset, including user area packets of the OTPC emulation mode. However, those packets remain ignored by the ROM code unless the proper value is written into the BSCR register, for instance by executing the writecfg:bscr:EMULATION_ENABLED command:

    $ sam-ba -p serial -b sam9x60-ek -t 5 -a bootconfig -c writecfg:bscr:EMULATION_ENABLED

Setting bit 0 (EMULATION_ENABLED) in the BSCR does not enable the OTPC emulation mode immediately: it only tells the ROM code to enable the OTPC emulation mode on the next reset before fetching the Boot Configuration packet and any other user area packet.

WARNING: once any user area packet has been programmed into the OTP matrix, the emulation mode can never be enabled again. Be careful before writing a packet in the OTPC matrix !

To prevent the user from writing a packet into the OTP matrix by mistake, SAM-BA requires the user to append an explicit emul or otp suffix to the packet type telling whether this packet is stored into the OTP matrix or into SRAM1.

Packet type / Stored in | SRAM1 (emulation mode) | OTP matrix
--- | --- | ---
Boot Configuration | bcp-emul | bcp-otp
Secure Boot Configuration | sbcp-emul | sbcp-otp
User Hardware Configuration | uhcp-emul | uhcp-otp

Before writing a first packet in emulation mode, SRAM1 must be reset to zero. This is the purpose of the resetemul command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -c resetemul

Once SRAM1 has been reset, the user should request the OTPC to scan again, hence refresh, packets in the user area by running a refreshcfg:emul command.

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c refreshcfg:emul

Unlike the writecfg:bscr:EMULATION_ENABLED, the refreshcfg:emul command enables the OTPC emulation mode immediately, till the next power-on/reset or till disable again by the refreshcfg:otp command.

## Boot Configuration

The ROM code of SAM9X60 devices is the 1st stage boot loader responsible for the system boot. Hence, the ROM code fetches the active Boot Configuration packet from the OTPC in order to get boot settings such as the ROM code console and the NVM boot sequence.

### Active Boot Configuration packet

ROM code boot settings are stored in an OTPC packet of Boot Configuration type. Like any other OTPC packet, Boot Configuration packets can be read, programmed, locked or invalidated.

The latest valid Boot Configuration packet is the active Boot Configuration packet. That is to say the ROM code fetches its boot settings from this packet.

If no valid Boot Configuration packet is programmed in the OTPC, then the ROM code uses its default console and default boot sequence .

### ROM Code console

The Boot Configuration packet tells the ROM code which RS-232 UART is to be used for the console. For instance, the "RomBOOT" string is always printed on power-on or reset on this console. Also, the ROM code console is used by SAM-BA monitors to communicate with the sam-ba program when USB is not available.

On SAM9X60, the default ROM code console is DBGU but it can be set to some FLEXCOMx USART. Please note that the ROM code console may be different from the applet console

### NVM boot sequence

The Non-Volatile Memory (NVM) boot sequence is the list of controllers managing external NVM where the ROM code tries to load the user application (or 2nd stage boot loader) from.

On SAM9X60, the default boot sequence is:

1. SDMMC0 (e.MMC / SD Card)
2. SDMMC1 (e.MMC / SD Card)
3. QSPI (QSPI NOR flash)
4. FLEXCOM0 SPI (SPI NOR flash)
5. SMC (raw NAND flash)

All the possible values for the memory interfaces and IOsets for SAM9X60 devices can be obtained by

    $ sam-ba -p serial -d sam9x60 -t 5 -a bootconfig -c help

### Programming a Boot Configuration packet

The user can program his first Boot Configuration packet with the writecfg:bcp-emul / writecfg:bcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:bcp-emul:QSPI0_IOSET1

In this example, DBGU is implicitly chosen as the ROM code console and QSPI0 is the only boot media in the boot sequence.

If the user wants to try to boot from a NAND flash first, then from SDMMC1 then the sam-ba command will be:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:bcp-emul:NFC_IOSET1,SDMMC1_IOSET1

The writecfg command fails on purpose to create a new packet if an active packet of the same type already exists but cannot be updated. This packet must be invalidated first by the invalidatecfg command before creating a new valid packet.

### Reading back the Boot Configuration packet

If an active Boot Configuration packet is available from the OTPC, this packet can be read-back with the readcfg:bcp-emul / readcfg:bcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c readcfg:bcp-emul

If no active Boot Configuration packet is available from the OTPC, then this command reports an error. Especially, the default boot configuration used by the ROM code is not returned. Only the active Boot Configuration packet programmed in the OTPC can be returned.

### Updating the Boot Configuration packet

Only 32-bit zero words can be updated in OTPC packet payloads. For instance, if the boot sequence is not full, the user can append another entry to the boot sequence. However, previous entries must be left unchanged. As an example, assuming the current boot sequence is "NFC_IOSET1,SDMMC1_IOSET1", the user can still append a "SDMMC0_IOSET1" entry with the writecfg:bcp-emul / writecfg:bcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:bcp-emul:NFC_IOSET1,SDMMC1_IOSET1,SDMMC0_IOSET1

The update or the creation of new Boot Configuration packet can be persistently disabled by setting the BCPGDIS bit of the User Hardware Configuration packet.

### Locking the Boot Configuration packet

Locking a packet discards any further modification of this packet, except its invalidation. Hence, once locked, a packet can no longer be updated. Locking the Boot Configuration packet is done by the lockcfg:bcp-emul / lockcfg:bcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c lockcfg:bcp-emul
    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:bcp-emul:NFC_IOSET1,SDMMC1_IOSET1,SDMMC0_IOSET1,FLEXCOM0_SPI_IOSET1

The second command fails since the Boot Configuration packet has been locked by the first command.

Locking of Boot Configuration packets can be persistently disabled by setting the BCLKDIS bit of the User Hardware Configuration packet.

### Invalidating the Boot Configuration packet

The Boot Configuration packet can be tagged as invalid so it is ignored by the OTPC when it scans the user area, hence ignored by the ROM code on futher power-on/reset. This is achieved with the invalidatecfg:bcp-emul / invalidatecfg:bcp-otp command

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c invalidatecfg:bcp-emul

Packet invalidation cannot be reverted, however a new packet of the same type can be programmed with a new writecfg:bcp-emul/ writecfg:otp-emul command. In case of Boot Configuration packets, the latest packet that has been programmed but not invalidated yet is the active Boot Configuration packet.

    $ sam-ba -p serial -ba sam9x60 -a bootconfig -t 5 -c writecfg:bcp-emul:NFC_IOSET1

The invalidation of Boot Configuration packets can be persistently disabled by setting the BCINVDIS bit of the User Hardware Configuration packet.

## User Hardware Configuration

The User Hardware Configuration packet is designed for the user to persistently disable the JTAG port or some OTPC features and commands.

Like with the Boot Configuration packet, sam-ba provides commands to create, read-back, update, lock and invalidate the User Hardware Configuration packet.

When a User Hardware Configuration packet has been created or updated, the packet is not taken into account by the OTPC controller until the next power-on/reset or until a refresh operation has been triggered by the refreshcfg command.

After each refresh, The payload of the active User Hardware Configuration packet is visible from OTPC_UHC0R and OTPC_UHC1R registers. Please refer to the OTPC section of the SAM9X60 datasheet for the exact description of those registers.

The User Hardware Configuration packet should be programmed at the end of the production to persistenly disable OTPC features such as programming, locking or invalidating given types of packet that may be used as breaches into the security of the customer device.

This is done with the writecfg:uhcp-emul / writecfg:uhcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:uhcp-emul:JTAGDIS,BCPGDIS,BCINVDIS,UHCPGDIS,UHCINVDIS

## Secure Boot Configuration

To enable the secure boot mode on SAM9X60 devices, an initial Secure Boot Configuration packet must be created with the writecfg:sbcp-emul / writecfg:sbcp-otp command:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:sbcp-emul:SECURE_BOOT_ENABLED

or shortly:

    $ sam-ba -p serial -b sam9x60-ek -a bootconfig -t 5 -c writecfg:sbcp-emul:

Don't forget the final colon (:) after sbcp-emul as the writecfg command expects 2 arguments; the 2nd argument being left to its default SECURE_BOOT_ENABLED value.

For further details on how to configure the secure boot mode, refer to Secure Boot Mode.

## Programming a raw NAND flash

In the following example, we program the at91bootstrap.bin, u-boot.bin, zImage, at91-sam9x60ek.dtb and rootfs.ubi files into the embedded NAND flash of a SAM9X60-EK board:

    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c erase
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c writeboot:at91bootstrap.bin -c verifyboot:at91bootstrap.bin
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c write:u-boot.bin:0x00040000 -c verify:u-boot.bin:0x00040000
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c write:at91-sam9x60ek.dtb:0x00180000 -c verify:at91-sam9x60ek.dtb:0x00180000
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c write:zImage:0x00200000 -c verify:zImage:0x00200000
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a nandflash -c write:rootfs.ubi:0x00800000 -c verify:rootfs.ubi:0x00800000

If the raw NAND flash is connected to a custom board design, then additional parameters should be passed to the -a nandflash option in above examples.

The list of those parameters is given by the command:

    $ sam-ba -p serial -d sam9x60 -a nandflash:help
    Syntax: nandflash:[<ioset>]:[<bus_width>]:[<header>]
    Parameters:
        ioset      I/O set
        bus_width  NAND bus width (8/16)
        header     NAND header value
    Examples:
        nandflash                 use default board settings
        nandflash:2:8:0xc0098da5  use fully custom settings (IOSET2, 8-bit bus, header is 0xc0098da5)
        nandflash:::0xc0098da5    use default board settings but force header to 0xc0098da5
    For information on NAND header values, please refer to SAM9X60 datasheet section "11.4.7.1.1 Method 1 (recommended): NAND Flash Specific Header Detection".

Supported <ioset> for the NAND flash on SAM9X60 devices are listed here.

## Programming a QSPI NOR flash

In the following example, we program the at91bootstrap.bin, u-boot.bin, zImage and at91-sam9x60ek.dtb files into the embedded QSPI NOR flash of the SAM9X60-EK board:

    $ sam-ba -p serial -b sam9x60-ek -t 5 -a qspiflash -c erase
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a qspiflash -c writeboot:at91bootstrap.bin -c verifyboot:at91bootstrap.bin
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a qspiflash -c write:u-boot.bin:0x00040000 -c verify:u-boot.bin:0x00040000
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a qspiflash -c write:at91-sam9x60ek.dtb:0x00180000 -c verify:at91-sam9x60ek.dtb:0x00180000
    $ sam-ba -p serial -b sam9x60-ek -t 5 -a qspiflash -c write:zImage:0x00200000 -c verify:zImage:0x00200000

Most QSPI NOR flash memories are too small to store the Linux root file-system; this should be programmed into another NVM.

If the QSPI NOR flash memory is connected to a custom board design, then additional parameters should be passed to the -a qspiflash option in above examples.

The list of those parameters is given by the command:

    $ sam-ba -p serial -d sam9x60 -a qspiflash:help
    Syntax: qspiflash:[<instance>]:[<ioset>]:[<frequency>]
    Parameters:
        instance   QSPI controller instance
        ioset      QSPI I/O set
        frequency  QSPI clock frequency in MHz
    Examples:
        qspiflash         use default board settings
        qspiflash:0:3:66  use fully custom settings (QSPI0, IOSET3, 66Mhz)
        qspiflash:::20    use default board settings but force frequency to 20Mhz

Supported <instance> and <ioset> for QSPI on SAM9X60 devices are listed here.

## Programming a SPI NOR flash

In the following example, we program the at91bootstrap.bin, u-boot.bin, zImage and at91-sam9x60ek.dtb files into some SPI NOR flash connected to the FLEXCOM0_SPI of a SAM9X60-based board:

    $ sam-ba -p serial -d sam9x60 -t 5 -a serialflash:0:1:50 -c erase
    $ sam-ba -p serial -d sam9x60 -t 5 -a serialflash:0:1:50 -c writeboot:at91bootstrap.bin -c verifyboot:at91bootstrap.bin
    $ sam-ba -p serial -d sam9x60 -t 5 -a serialflash:0:1:50 -c write:u-boot.bin:0x00008000 -c verify:u-boot.bin:0x00008000
    $ sam-ba -p serial -d sam9x60 -t 5 -a serialflash:0:1:50 -c write:at91-sam9x60ek.dtb:0x00060000 -c verify:at91-sam9x60ek.dtb:0x00060000
    $ sam-ba -p serial -d sam9x60 -t 5 -a serialflash:0:1:50 -c write:zImage:0x0006c000 -c verify:zImage:0x0006c000

SPI NOR flashes are likely to be too small to store the Linux root file-system; this should be programmed into another NVM.

If the SPI NOR flash memory is connected to a custom board design, then additional parameters should be passed to the -a serialflash option in above examples.

The list of those parameters is given by the command:

    $ sam-ba -p serial -d sam9x60 -a serialflash:help
    Syntax: serialflash:[<instance>]:[<ioset>]:[<npcs>]:[<frequency>]
    Parameters:
        instance   SPI controller instance
        ioset      I/O set
        npcs       SPI chip select number
        frequency  SPI clock frequency in MHz
    Examples:
        serialflash           use default board settings
        serialflash:0:1:0:66  use fully custom settings (SPI0, IOSET1, NPCS0, 66Mhz)
        serialflash::::20     use default board settings but force frequency to 20Mhz

Supported <instance>, <ioset> and <npcs> for SPI on SAM9X60 devices are listed here.

## Programming a SDCard or e.MMC user partition

In the following example, the sdcard.img file is a raw image of a SD Card, hence starting with a Master Boot Record (MBR) containing a valid partition table. The first partition is formatted with a FAT32 file-system, which gathers four files in its root directory:

- a boot.bin file: the at91bootstrap.bin file renammed into boot.bin
- a u-boot.bin file: the u-boot binary image, loaded then executed by boot.bin
- a zImage file: the compressed image of a Linux kernel, loaded then executed by u-boot
- a at91-sam9x60ek.dtb: the device-tree binary for the Linux kernel, loaded by u-boot at the same time as the zImage file

The second partition is formatted in EXT4 and contains the root file-system used by the Linux kernel

    $ sam-ba -p serial -b sam9x60-ek -t 5 -a sdmmc -c write:sdcard.img

If the SD Card or e.MMC memory is connected to a customer board design, then additional parameters should be passed to the -a sdmmc option in above examples.

The list of those parameters is given by the command:

    $ sam-ba -p serial -d sam9x60 -a sdmmc:help
    Syntax: sdmmc:[<instance>]:[<ioset>]:[<partition>]:[<bus_width>]:[<voltages>]
    Parameters:
        instance   SDMMC controller number
        ioset      SDMMC I/O set
        partition  Partition number (0=user partition, x>0=boot partition x)
        bus_width  Data bus width (0=controller max, 1=1-bit, 4=4-bit, 8=8-bit)
        voltages   Supported voltages (bitfield: 1=1.8V, 2=3.0V, 4=3.3V)
    Examples:
        sdmmc           use default board settings
        sdmmc:0:1:1:8:5 use fully custom settings (SDMMC0, IOSET1, first boot partition, 8-bit, 1.8V/3.3V)
        sdmmc:0::1      use default board settings but force use of SDMMC0, first boot partition

Supported <instance> and <ioset> for SDMMC on SAM9X60 devices are listed here.

## Secure Boot Mode

First step to benefit from secure boot features of SAM9X60 devices is to enable this secure boot mode as describe in section Secure Boot Configuration.

Once the Secure Boot Configuration packet has been written, the device must be reset so the ROM code executes its secure SAM-BA monitor:

    $ sam-ba -p serial -d sam9x60 -a reset

From this point, the ROM code no longer executes its non-secure SAM-BA monitor but instead runs its secure SAM-BA monitor. Hence, the serial or j-link ports cannot be used; the secure port must be used instead.

Then, another mandatory step is to program the customer key into the device. This customer key is wrapped into a ciphered and signed customer key message.

This so called customer key message is actually generated from the 640-bit customer key by the secure-sam-ba-cipher.py tool. This tool is distributed under NDA, hence not covered by this documentation.

As stated, the customer key message is ciphered to protect the customer key from eavesdropping during device provisioning in factory and is also signed so the customer key message can be authenticated by the ROM code. Only the secure-sam-ba-cipher.py tool with a license provided by Microchip can generate genuine customer key messages.

Assumming the customer key message is packaged inside a customer-key.cip file, programming the customer key into the SAM9X60 device must be done by sam-ba with this command:

    $ sam-ba -p secure -b sam9x60-ek -m write_customer_key:customer-key.cip

At this point and on further resets, the ROM code expects the bootstrap or user application stored into the external NVM to be both ciphered with AES-256-CBC and signed with AES-256-CMAC.

Optionally, the shared key signature algorithm can be replaced by a public key algorithm. More precisely, the AES-256-CMAC signature is replaced by a RSA signature that will be verified by the ROM code at each boot to authenticate the bootstrap or user application.

Indeed, a chain of X.509 version 3 certificates in DER format is concatenated to the bootstrap and its RSA signature.

The first certicate in this chain is called the root certificate and must be a self-signed certificate.

Besides, except the root certificate, each certificate in the chain is signed, hence authenticated, by the previous certificate in the chain. So the root certificate, more precisely its public key, is the root of trust since it, directly or indirectly, authenticates all certificates in the chain.

The secure-sam-ba-cipher.py tool can compute a SHA-256 digest of the public key of the root certificate. Like the customer key with the customer key message, this digest is wrapped into a ciphered and signed message called the RSA hash message.

The generation of the RSA hash message by secure-sam-ba-ciher.py is not covered by this documentation.

Then, assuming the SHA-256 digest of the public key of the X.509 root certificate is packaged inside a root-cert-hash.cip file, programming the digest into the SAM9X60 device must be done by sam-ba with the following command:

    $ sam-ba -p secure -b sam9x60-ek -m write_rsa_hash:root-cert-hash.cip

After that and for each boot, the ROM code still deciphers the bootstrap or the user application with the AES-256-CBC algorithm using the same shared key as before but no longer authenticates it with an AES-256-CMAC signature.

Instead, it computes the SHA-256 digest of the public key of the root certificate with the same algorithm used by the secure-sam-ba-cipher.py tool. Then, the ROM code authenticates the root certificate by comparing the computed digest with the one that has been programmed into the OTPC with the write_rsa_hash command.

If both digests match then the root certificate is authenticated by the ROM code. Next, the ROM code authenticates each X.509 certificate of the chain by verifying its signature with the public key of the previous X.509 certificate in the chain.

Finally, when all X.509 certificates in the chain have been authenticated, the ROM code uses the public key stored into the last certificate of the chain to verify the RSA signature of the bootstrap or user application stored in NVM.

To speed-up the boot process, the X.509 certificate chain can be limited to a single X.509 self-signed certificate. In such case, this certificate is both the root certificate and the certificate used to authenticate the bootstrap or user application.

Both 2048 and 4096-bit RSA signatures are supported by the SAM9X60 devices.

### Enabling the pairing mode

The pairing mode enhances the secure boot mode with an anti-cloning protection for the target device.

The user can enable this mode with the following built-in monitor command:

    $ sam-ba -p secure -d sam9x60 -m enable_pairing