OpenNuvoton / NuMaker-mbed-TZ-nonsecure-example

NuMaker mbed Trustzone nonsecure example
1 stars 0 forks source link

Example for non-PSA secure/non-secure code on Nuvoton TrustZone targets

This is an example to demonstrate non-PSA secure/non-secure code running on Nuvoton TrustZone targets.

Supported platforms

In the following, we take NuMaker-PFM-M2351/NuMaker-M2354 as examples for explanation.

Supported toolchain

In the following, we compile our program with ARMCLANG toolchain.

Partition the hardware

On TrustZone targets, it is necessary to partition the hardware first for secure/non-secure code to run on secure/non-secure worlds respectively.

On Nuvoton's TrustZone chips, it is necessary to Mass Erase the chip first by external tool e.g. ICP Tool before we can partition the hardware (only once). Fortunately, if we flash secure code through drag-n-drop, Nu-Link/Nu-Link2 would issue Mass Erase in its erase/program flow. With that, secure code can get one chance to re-partition the hardware without resorting to other tools.

Partition the flash

In the following example, we would partition the flash into secure/non-secure worlds, where flash addresses start at 0x00000000/(0x10000000 + Secure Flash Size) respectively:

Partition the SRAM

In the following example, we would partition the SRAM into secure/non-secure worlds, where SRAM addresses start at 0x20000000/(0x30000000 + Secure SRAM Size) respectively:

Partition the peripherals

TODO

Compile TrustZone non-PSA secure code

Follow the steps below to compile TrustZone non-PSA secure code.

  1. Clone NuMaker-mbed-TZ-secure-example

    mbed import https://github.com/OpenNuvoton/NuMaker-mbed-TZ-secure-example
    cd NuMaker-mbed-TZ-secure-example
  2. Tell Mbed of secure flash/SRAM partition for secure world

    To compile TrustZone non-PSA secure code, we need to tell Mbed build system of secure flash/SRAM partition for secure world. The step is required.

    • M2351:
      {
      "target_overrides": {
          ......
          "NU_PFM_M2351_NPSA_S": {
              ......
              "target.mbed_rom_start"             : "0x0",
              "target.mbed_rom_size"              : "0x40000",
              "target.mbed_ram_start"             : "0x20000000",
              "target.mbed_ram_size"              : "0x8000",
              ......
          }
      }
      }
    • M2354:
      {
      "target_overrides": {
          ......
          "NU_M2354_NPSA_S": {
              ......
              "target.mbed_rom_start"             : "0x0",
              "target.mbed_rom_size"              : "0x80000",
              "target.mbed_ram_start"             : "0x20000000",
              "target.mbed_ram_size"              : "0x20000"
              ......
          }
      }
      }
  3. Don't enable RTOS

    The secure code runs with RTOS disabled. Secure code with RTOS is not supported yet.

    {
        "requires": ["bare-metal", "rtos-api"],
        ......
    }
  4. Adjust TZ process max stack slots/stack size

    "macros": [
        "MBED_CONF_TZ_PROCESS_STACK_SLOTS=8",
        "MBED_CONF_TZ_PROCESS_STACK_SIZE=2048",
        ......
    ],

    NOTE1: TZ max stack slots MBED_CONF_TZ_PROCESS_STACK_SLOTS limits max NS threads which enable TZ access MBED_TZ_DEFAULT_ACCESS.

    NOTE2: TZ stack size MBED_CONF_TZ_PROCESS_STACK_SIZE is for secure library (NSC function). Its value is enlarged for custom NSC function.

    NOTE3: Avoid printf-like call in NSC function because it needs large stack and runs the risk of stack overflow.

  5. Tell Mbed of boot stack size when RTOS is absent for secure world (optional, preferred)

    The default boot stack size when RTOS is absent may not meet your requirement. Change it explicitly.

    • M2351:
      {
      "target_overrides": {
          ......
          "NU_PFM_M2351_NPSA_S": {
              ......
              "target.boot-stack-size"            : "0x1000",
              ......
          }
      }
      }
    • M2354: Default boot stack size is fine, so no change to it.
  6. Enable serial and so printf (optional, not preferred)

    To run with serial enabled, add "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", and "STDIO_MESSAGES" in the configuration option target.device_has_add.

    • M2351:
      {
      "target_overrides": {
          ......
          "NU_PFM_M2351_NPSA_S": {
              ......
              "target.device_has_add": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
              ......
          }
      }
      }
    • M2351: Serial defaults to enabled.

    Besides, disable STDIO buffered serial explicitly as well. STDIO buffered serial needs USB UART INT. By default, both USB UART and its INT are configured as non-secure. Even though secure code can control this UART via non-secure data access, there's no USB UART INT in secure side. So disable this function explicitly for safe.

    {
        "target_overrides": {
            "*": {
                ......
                "platform.stdio-buffered-serial"    : false,
                ......
            },
            ......
        }
    }

    To run with serial disabled, add "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", and "STDIO_MESSAGES" in the configuration option target.device_has_remove.

    • M2351:
      {
      "target_overrides": {
          ......
          "NU_PFM_M2351_NPSA_S": {
              ......
              "target.device_has_remove": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
              ......
          }
      }
      }
    • M2354:
      {
      "target_overrides": {
          ......
          "NU_M2354_NPSA_S": {
              ......
              "target.device_has_remove": ["SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES"],
              ......
          }
      }
      }
  7. Enable fault handler dump message (optional)

    {
        "target_overrides": {
            ......
            "NU_PFM_M2351_NPSA_S": {
                ......
                "target.macros_remove": ["MBED_FAULT_HANDLER_DISABLED"],
                ......
            },
            "NU_M2354_NPSA_S": {
                ......
                "target.macros_remove": ["MBED_FAULT_HANDLER_DISABLED"],
                ......
            }
        }
    }

    NOTE: This gets unnecessary when fault handler dump message gets to enabled by default in future Mbed OS version.

  8. Change non-secure jump address (optional)

    This is done by configuring tz-start-ns in mbed_app.json or custom one. If not specified, it defaults to start of non-secure flash. To jump to non-default non-secure address like:

    • M2351: 0x10044000
    • M2354: 0x10084000

    mbed_app.json or custom one would have:

    • M2351:
      {
      "target_overrides": {
          ......
          "NU_PFM_M2351_NPSA_S": {
              ......
              "tz-start-ns": "0x10044000",
              ......
          }
      }
      }
    • M2354:
      {
      "target_overrides": {
          ......
          "NU_M2354_NPSA_S": {
              ......
              "tz-start-ns": "0x10084000",
              ......
          }
      }
      }
  9. Compile by running command:

    • M2351:
      mbed compile -m NU_PFM_M2351_NPSA_S -t ARM --app-config mbed_app_custom.json
    • M2354:
      mbed compile -m NU_M2354_NPSA_S -t ARM --app-config mbed_app_custom.json
  10. Keep compiled secure code for non-secure code build process later

    • M2351:

      • BUILD/NU_PFM_M2351_NPSA_S/ARM/NuMaker-mbed-TZ-secure-example.hex
      • BUILD/NU_PFM_M2351_NPSA_S/ARM/cmse-lib.o
    • M2354:

      • BUILD/NU_M2354_NPSA_S/ARM/NuMaker-mbed-TZ-secure-example.hex
      • BUILD/NU_M2354_NPSA_S/ARM/cmse-lib.o

Compile TrustZone non-PSA non-secure code

Follow the steps below to compile TrustZone non-PSA non-secure code.

  1. Clone NuMaker-mbed-TZ-nonsecure-example

    mbed import https://github.com/OpenNuvoton/NuMaker-mbed-TZ-nonsecure-example
    cd NuMaker-mbed-TZ-nonsecure-example`
  2. Tell Mbed of non-secure flash/SRAM partition for non-secure world

    To compile TrustZone non-secure code, we need to tell Mbed build system of non-secure flash/SRAM partition for non-secure world. If we skip the step, default non-secure partition would be applied. Usually, the step is required if we compile our own secure code as above which would change the default partition.

    • M2351:
      "target_overrides": {
      ......
      "NU_PFM_M2351_NPSA_NS": {
          ......
          "target.mbed_rom_start"             : "0x10040000",
          "target.mbed_rom_size"              : "0x40000",
          "target.mbed_ram_start"             : "0x30008000",
          "target.mbed_ram_size"              : "0x10000",
          .......
      }
      }
    • M2354:
      "target_overrides": {
      ......
      "NU_M2354_NPSA_NS": {
          ......
          "target.mbed_rom_start"             : "0x10080000",
          "target.mbed_rom_size"              : "0x80000",
          "target.mbed_ram_start"             : "0x30020000",
          "target.mbed_ram_size"              : "0x20000",
          ......
      }
      }
  3. Exclude pre-built secure image/gateway library

    There has been a pre-built secure code in mbed-os directory tree. To link with our own one as above, we must exclude the pre-built one.

    • M2351:
      "target_overrides": {
      ......
      "NU_PFM_M2351_NPSA_NS": {
          "target.extra_labels_remove"        : ["NU_PREBUILD_SECURE"],
          ......
      }
      }
    • M2354:
      "target_overrides": {
      ......
      "NU_M2354_NPSA_NS": {
          "target.extra_labels_remove"        : ["NU_PREBUILD_SECURE"],
          ......
      }
      }
  4. Add compiled secure code above into non-secure code build process

    Create one directory named below in the root of the example, and copy NuMaker-mbed-TZ-secure-example.hex/cmse_lib.o (just built above) there:

    • M2351: TARGET_NU_PFM_M2351_NPSA_NS
    • M2354: TARGET_NU_M2354_NPSA_NS
  5. Compile by running command:

    • M2351:

      mbed compile -m NU_PFM_M2351_NPSA_NS -t ARM --app-config mbed_app_custom.json
    • M2354:

      mbed compile -m NU_M2354_NPSA_NS -t ARM --app-config mbed_app_custom.json
  6. Flash compiled secure/non-secure code together

    Drag-n-drop below to flash compiled secure/non-secure code together:

    • M2351:

    BUILD/NU_PFM_M2351_NPSA_NS/ARM/NuMaker-mbed-TZ-nonsecure-example.hex onto NuMaker-PFM-M2351 board

    • M2354:

    BUILD/NU_M2354_NPSA_NS/ARM/NuMaker-mbed-TZ-nonsecure-example.hex onto NuMaker-M2354 board

Execution

If everything goes well, you would see console log emitted by non-secure code like:

+---------------------------------------------+
|    Non-secure code is running ...           |
+---------------------------------------------+
Non-secure main thread: 0 
Non-secure main thread: 1 
Non-secure main thread: 2 
Non-secure main thread: 3 
Non-secure main thread: 4 

You would also see console log emitted by secure code in the front if serial is enabled in it.

NOTE: Configure your terminal program to 115200/8-N-1.