장치 펌웨어 업데이트를 수행하기 전에 새 이미지를 확인해야 한다.
일부 정보(예:호환성)는 실제 펌웨어가 전송되기 전에 확인할 수 있다.(prevalidation)
이미지의 해시와 같은 기타 정보는 전송 후 유효성을 검사해야 한다.(postvalication)
제공된 펌웨어 패키지에는 펌웨어 이미지와 이미지를 사전 검증하는데 사용할 수 있는
초기화 패킷이 포함되어야 한다. 초기화 패킷의 형식과 실제 유효성 검사 프로세스는
DFU 부트로더 구현에 의해 정의된다. BLE Secure DFU Bootloader예제에서 사용되는
검증에 대한 문서는 Init packet를 참조한다.
호환성을 위해 유효성 검사(DFU 부트로더 구현의 일부)와 이미지 생성(일반적으로 외부 도구로
수행)은 동일한 초기화 패킷 형식을 사용해야 한다. 공통 형식을 보장하는 편리한 방법은
프로토콜 버퍼 파일에서 초기화 패킷의 필수 내용을 정의하는 것이다. 이러한 방식으로
패킷 형식을 한 번 정의한 다음 다른 위치에서 사용할 수 있다.
구현 예는 BLE Secure DFU Bootloader를 참조한다.
1. Init packet
DFU를 수행할 때 펌웨어 이미지, 초기화 패킷 및 패키지 형식을 나타내는 매니페스트 파일이
포함된 패키지(zip형식)를 제공해야한다. 초기화 패킷에는 이미지의 유효성을 검사하는데
사용되는 펌웨어 이미지에 대한 정보가 포함되어 있으며 업데이트가 신뢰할 수 있는
소스에서 제공되도록 서명해야 한다.
Nordic은 프로토콜 버퍼 파일에 의해 정의된 형식의 초기화 패킷으로 펌웨어 패키지를
생성하는 명령줄 도구 nrfutil을 제공한다. nrfutil을 사용하여 BLE Secure DFU Bootloader
예제와 호환되는 펌웨어 패키지를 만드는 방법에 대한 정보는
Creating a firmware package with nrfutil를 참조한다. DFU 부트로더 구현에서 초기화 패킷의
형식을 변경하는 경우 도구를 업데이트하는 방법에 대한 지침은 nrfutil documentation을 참조한다.
또는 도구를 만들어 펌웨어 패키지를 생성할 수 있다.
초기화 패킷의 필수 내용은 프로토콜 버퍼 파일 dfu-cc.proto에 정의되어 있다.
초기화 패킷의 다음 필드는 초기화 패킷의 유효성 검사 중에 확인된다.
| Type | Field name | Description |
| Type of the image | type | 이미지는 어플리케이션 이미지, SoftDevice 이미지, 부트로더 이미지 또는 부트로더와 SoftDevice의 결합된 이미지 일 수 있다. |
| Hash of the image | hash | 해시는 사용된 해시 함수를 지정하는 정수와 전체 패키지의 해시를 포함하는 바이트 배열의 두 필드로 구성된다. |
| Firmware version | fw_version | 이 정수는 패키지의 부트로더 또는 어플리케이션 이미지의 펌웨어 버전을 나타낸다.(SoftDevice 버전은 별도의 필드에 지정된다.) |
| Hardware version | hw_version | 이 정수는 장치의 필요한 하드웨어 버전을 나타낸다. |
| Allowed versions of the SoftDevice | sd_req[] | 이 정수 배열은 이미지에 허용되는 SoftDevice 펌웨어 ID를 나타낸다. 최대 16개의 허용된 SoftDevice버전을 지정할 수 있다. |
| Size of the new SoftDevice, bootloader, or application | sd_size, bl_size, app_size | 이 정수 값은 SoftDevice, 부트로더 또는 어플리케이션의 크기를 지정한다. |
| Signature type | signature_type | 초기화 패킷이 서명되는 서명 유형이다. DFU코드는 ECDSA_P256_SHA256을 지원한다. |
| Signature | signature | Cryptography library - nrf_crypto참조 |
| Debugging | is_debug | 이 플레그가 Set되면 버전 유효성 검사(Validation참조)를 건너뛴다. 이 플래그는 디버그 프로젝트에서만 적용된다. 디버그가 아닌 프로젝트는 항상 버전의 유효성을 검사한다. |
2. Creating a firmware package with nrfutil
펌웨어 이미지(또는 이미지)와 해당 초기화 패킷이 포함된 zip파일을 생성하려면
nrfutil 도구(버전 2.2.0이상)을 사용한다. 이 도구는 Nordic Semiconductor nrfutil GitHub repository에서
독립 실행형 Python 패키지로 제공되거나 pip install nrfutil을 사용하여 pypi에서
설치할 수 있다. 자세한 내용은 nrfutil documentation을 참조한다.
nrfutil pkg generate --help를 실행하여 zip 파일 생성에 대한 도움말을 표시한다.
다음 펌웨어 이미지를 2진 또는 16진 형식으로 zip파일에 추가할 수 있다.
- --application image: an image of an application
- --bootloader image: an image of a bootloader
- --softdevice image: an image of a SoftDevice
하나의 zip파일에 여러 이미지를 결합할 수도 있다. 이미지 조합에 따라 생성된
zip파일에 두 개의 펌웨어 패키지(하나는 부트로더 and/or SoftDevice용,
하나는 어플리케이션용)가 포함될 수 있으며 DFU 프로세스는 두 단계로 수행된다.
펌웨어 패키지에 부트로더와 SoftDevice를 모두 포함하면 두 이미지가 함께 병합된다.
그러나 응용 프로그램은 다른 업데이트가 완료된 후 항상 별도로 업데이트 된다.
이미지 외에도 초기화 패킷에 추가할 정보를 지정한다. 다음 옵션을 사용할 수 있다.
| Option | Example value | Description |
| --debug-mode | n/a | 버전 유효성 검사를 건너 뛰려면 이 플래그를 추가한다. |
| --key-file | c:\vault\priv.pem | 펌웨어 이미지에 암호 방식으로 서명하는데 사용되는 PEM형식의 개인(서명)키. (Working with keys참조) |
| --application-version | 0xff | 어플리케이션 이미지의 버전 |
| --bootloader-version | 0xff | 부트로더 이미지의 버전 |
| --hw-version | 52 | 이미지를 승인해야 하는 하드웨어 버전 |
| --sd-req | 0x87,0x8C,0xAE,0xAF,0xB0 | 새 이미지와 함께 사용하기에 유효한 설치된 대상 SoftDevice의 FWID값을 쉼표로 구분한 목록. nrfutil pkg generate --help를 실행하여 가능한 값 목록을 표시. |
SoftDevice+Bootloader+어플리케이션 업데이트의 경우 --sd-id 필드도 지정해 주어야 한다.
nrfutil 및 초기화 패킷을 사용자 정의하려는 경우 필요한 단계에 대한
추가 정보는 nrfutil documentation을 참조한다.
3. Validation
이미지 유효성 검사에는 이미지가 신뢰할 수 있는 출처에서 제공되고 장치 및 현재 펌웨어 및 하드웨어와
호환되는지 확인하는 검사가 포함된다.
플래그 is_debug가 초기화 패킷에 설정되어 있으면 예제의 디버그 버전은 버전 유효성 검사를 건너뛴다.
이러한 검사는 유효성 검사 모듈에서 구현된다. 확인은 다음 순서로 수행된다.
- Signature of the packet (signature)
서명을 확인할 수 있으려면 유효성 검사 코드에 초기화 패킷에 서명하는데 사용된 개인 키에
해당하는 공개키가 필요하다. 이 키는 dfu_public_key.c 파일에 있다. - Firmware type (fw_type)
NRF_DFU_APP_DOWNGRADE_PREVENTION구성으로 버전 확인을 활성화/비활성화할 수 있다. - Hardware version (hw_version)
- SoftDevice version (sd_req)
- Firmware version (fw_version)
- Firmware size to see whether the update will fit.
Dual-bank and single-bank updates는 허용되는 크기를 나타내는 Secure DFU 부트로더의
메모리 레이아웃을 보여준다.
이러한 확인 단계 중 하나가 실패하면 전송을 통해 오류 코드가 전송된다.
3.1 Version number
버전 번호에는 세가지 유형이 있다.
- Hardware version : 하드웨어 버전은 장치에 의해 결정된다.
예제 구현에서 장치의 하드웨어는 sdk_config 파일의 NRF_DFU_HW_VERSION매크로에
의해 지정된다. nRF52시리즈의 경우 기본 버전 번호는 52로 정의되어 있다.
그러나 이 기본 버전 번호를 제품에 사용해서는 안되며
고유한 버전 번호 지정 체계를 사용해야 한다. - SoftDevice firmware ID : SoftDevice 펌웨어 ID는 SoftDevice HEX 파일 내부에 저장되며
SD_FWID_GET매크로를 통해 검색된다. - Firmware version : 펌웨어 버전은 전송된 이미지에 따라 부트로더 버전 또는
어플리케이션 버전을 의미한다. 현재 버전 번호는 부트로더 설정 페이지에 저장된다.
어플리케이션 버전(nrf_dfu_settings_t::app_version) 및
부트로더 버전(nrf_dfu_settings_t::bootloader_version)은
전역변수 s_dfu_settings에서 검색할 수 있다.
부트로더 이미지가 programmed되면 버전 번호가 지워지고 0으로 초기화된다. 따라서 부트로더를 처음 프로그램한 후 현재 버전 번호로 부트로더 설정 페이지를 생성해야 한다. 자세한 내용은 Bootloader Settings page 및
nrfutil documentation을 참조한다.
3.2 Acceptance rules for versions
버전 유효성 검사를 건너뛰지 않는 한 dfu_handle_prevalidate()함수는 다음 허용 규칙을 적용하여 이미지가 허용되는지 여부를 결정한다.
- Hardware version : 초기화 패킷에 지정된 하드웨어 버전이 장치의 하드웨어와 일치하면 이미지가 승인된다.
- SoftDevice Firmware ID : 지정된 Firmware ID 중 하나가 현재의 SoftDevice의 ID와 일치하면 이미지가 승인된다.
sd_req목록의 Firmware ID 0x00은 "업데이트가 SoftDevice에 의존하지 않음"을 의미한다.
이것의 의미는 Updates without a SoftDevice를 참조한다. - Firmware version : 이미지에 부트로더가 포함된 경우 새 펌웨어 버전이 부트로더의 기존 버전보다 크면
이미지가 허용된다. 이미지에 어플리케이션이 포함된 경우 새 펌웨어 버전이 기존 펌웨어 버전보다 크거나 같으면
이미지가 허용된다. 이미지에 SoftDevice가 포함되어 있고 SoftDevice가 이미 있는 경우에는 fw_version을
기존 어플리케이션 버전과 비교하여 업데이트가 덮어쓸 수 있는지 여부를 확인한다.
3.2.1 Updates without a SoftDevice
부트로더 자체에 SoftDevice가 필요하지 않은 경우 SoftDevice 없이 업데이트를 처리할 수도 있다.
이러한 업데이트는 아래 설명된대로 sd_req값이 0x00으로 인식된다.
- 업데이트에 어플리케이션이 포함된 경우 : 해당 어플리케이션은 일반적으로 SoftDevice가 배치되는 MBR 뒤에
배치된다. SoftDevice가 있는 경우 sd_req목록에는 덮어 쓸 수 있도록 Firmware ID도 포함되어야 한다. - 업데이트에 SoftDevice만 포함된 경우 : SoftDevice가 이미 없는 경우에만 적용될 수 있다.
업데이트에는 덮어쓸 수 있도록 현재 어플리케이션 버전에 대해 확인해야 하는 fw_version도 포함되어야 한다. - 업데이트에 부트로더가 포함된 경우 : 현재 SoftDevice가 무시된다. SoftDevice는 현재 부트로더에 필요하지 않고
업데이트 뱅킹을 위한 공간이 필요한 경우에만 삭제된다.
빈 sd_req목록은 0x00을 포함하는 sd_req목록과 같다.
3.3 Signature Verification
업데이트가 서명되고 서명 확인이 검증되면 부트로더는 업데이트가 비트 단위로 올바른지 개인키 소유자가
내용을 승인했는지 확인할 수 있다. 즉, 개인키가 비밀로 유지되는 한 장치에 적용되는 업데이트를 완전히
제어할 수 있다. 부트로더에는 공개키 사본만 포함되어 있다. 이 키는 서명을 확인하는데 사용할 수 있지만
새 서명을 만드려면 개인키가 필요하다. 기본적으로 Secure Bootloader는 모든 업데이트에 유효한 서명을
요구하지만 NRF_DFU_REQUIRE_SIGNED_APP_UPDATE구성을 수정하여 이 요구사항을 끌 수 있다.
(Open Bootloader 또한 이를 보여준다.)
모든 업데이트에 대해 항상 서명을 요구하는 것이 좋다.
NRF_DFU_REQUIRE_SIGNED_APP_UPDATE의 목적을 위해 부트로더 자체가 SoftDevice를
필요로하지 않는 한(즉, 부트로더가 BLE_STACK_SUPPORT_REQD를 정의하는 경우) SoftDevice는
어플리케이션의 일부로 간주된다. 예를 들어 BLE부트로더는 SoftDevice를 사용하여 BLE를 통해 업데이트를
수신하므로 BLE_STACK_SUPPORT_REQD를 정의한다. 이 경우 SoftDevice는 부트로더의 일부로 간주되므로
NRF_DFU_REQUIRE_SIGNED_APP_UPDATE의 영향을 받지 않는다.