반응형

장치 펌웨어 업데이트(DFU)를 사용하여 nRF5 SoC 를 무선(OTA)으로 SoftDevice, 부트로더 또는 애플리케이션을 업데이트할 수 있다.

다음 예를 참조한다.

ANT protocol과 ANT-FS transport를 사용한다면 다음 예를 참조한다.

 

반응형
반응형

DFU(Secure Device Firmware Update)서비스는 장치에서 장치 펌웨어 업데이트를 수행하는데

필요한 정보를 제공한다.

이 서비스는 nRF5 장치에서 일반적인 장치 펌웨어 업데이트를 시연하기 위해

Nordic Semiconductor에서 정의한 독점 서비스이다.

 

Secure DFU 서비스의 UUID는 0xFE59이다.

서비스는 기본 서비스로 인스턴스화되어야 한다.

 

DFU 서비스는 다른 서비스에 의존하지 않는다.

이 서비스에는 다음 GATT sub-procedures에 대한 지원이 필수이다.

  • Write Characteristic Value
  • Write Characteristic Descriptor
  • Read Characteristic Descriptor
  • Notification

DFU서비스는 속성 프로트콜에 대한 새로운 오류 코드를 정의하지 않는다.

데이터 교환은 Little-endian(LSB 우선)순서이다.

API설명은 DFU BLE Service 를 참조한다.

1. Service characteristics

다음 특성은 필수 특성이다.

Characteristic name Requir properties Optional properties UUID
DFU Control Point Write, Notify   0x8EC90001-F315-4F60-9FB8-838830DAEA50
DFU Packet WriteWithoutResponse,
Notify
  0x8EC90002-F315-4F60-9FB8-838830DAEA50

이 서비스는 보안 요구 사항을 요구하지 않는다. 즉, 서비스의 모든 특성에 대해 암호화가 필수가 아니다.

그러나 가능한 경우 암호화를 사용해야 한다.

2. DFU Control Point

DFU Control Point 특성의 UUID는 0x0001이다.

DFU Control Point 특성은 DFU Process의 상태를 제어하는데 사용된다.

모든 DFU 절차는 이 특성에 작성하여 요청된다.

절차의 끝을 표시하는 응답은 notification으로 수신된다.

3. DFU Packet

DFU Packet 특성의 UUID는 0x0002이다.

이 특성은 장치 펌웨어 업데이트에 대한 데이터를 DFU패킷으로 수신한다.

 

각 패킷의 최대 크기는 connection의 Att MTU 크기로부터 파생된다.

DFU 서비스의 최대 Att MTU 크기는 256 Byte(NRF_SDH_BLE_GATT_MAX_MTU_SIZE에 저장됨)이며

DFU 패킷 특성의 최대 크기는 253 Byte(3 Byte는 쓰기시 opcode 및 handle ID에 사용됨)이다.

DFU 서비스와 더 큰 At MTU 크기를 협상하지 않은 경우, 예상되는 쓰기 최대 크기는 20 Byte이다.

(BLE_GATT_ATT_MTU_DEFAULT에서 opcode 및 handle ID에 사용되는 3바이트를 뺀 값)

간단하게하기 위해 아래 메세지 시퀀스 차트는 ATT MTU크기가 협상되지 않아 20Byte 쓰기가 사용되는

예를 보여준다.

패킷은 Little-endian(LSB 우선) 순서이여야 한다.

3. Message sequence charts

다음 메세지 시퀀스 차트는 각각 초기화 패킷과 펌웨어 이미지의 전송을 보여준다.

3.1 Transfer of an init packet

DFU 컨트롤러는 먼저 초기화 패킷이 성공적으로 전송 완료 되었는지 확인한다.

그렇지 않은 경우 DFU 컨트롤러가 부분적으로 전송되었는지 확인한다. 일부 데이터가 이미 전송된 경우 전송이

계속된다. 그렇지 않으면 DFU 컨트롤러는 Create 명령을 보내 새 데이터 개체를 만든 다음 초기화 패킷을 전송한다.

초기화 패킷을 사용할 수 있을 때 DFU 컨트롤러는 실행 명령을 실행하여 초기화 패킷의 유효성 검사를 시작한다.

3.2 Transfer of a firmware image

펌웨어 이미지는 연속적으로 전송되는 여러 데이터 개체로 분할된다.

데이터 개체의 전송이 실패하 경우(Power down등으로 인해) 다시 시작하는 대신 전송을 계속할 수 있다.

따라서, DFU 컨트롤러는 전송된 마지막 데이터 개체를 선택하여 시작하고 이것이 완전하고 유효한지 확인한다.

확인이 완료되면 실행 명령을 실행하고 다음 데이터 개체로 전송을 계속한다.

확인시 문제가 발견되면 DFU 컨트롤러는 필요한 경우(이 데이터 개체에 대한 전송이 아직 시작되지 않았거나

수신된 데이터가 손상된 경우) 새 데이터 개체를 생성하기 위해 Create 명령을 보내고 다음 데이터 개체를 전송한다.

 

모든 패킷이 전송되면 DFU 컨트롤러가 실행 명령을 실행하여 실제 펌웨어 업데이트를 트리거한다.

 

DFU 컨트롤러는 진행 상황을 추적할 책임이 있다. 각 선택 명령에 대한 응바에는 최대 개체 크기, 현재 오프셋 및

CRC에 대한 정보가 포함된다. 예를 들어 이미지 크기가 10kByte이고 최대 개체 크기가 4kByte인 경우

3개의 데이터 개체를 전송해야 한다. 반환된 오프셋이 6kByte인 경우 DFU 컨트롤러는 현재 개체가 전송할 두번째

개체이며 완전히 전송되지 않았음을 알고 있다.

4. Data reliability

BLE DFU 서비스는 직렬화된 개체를 처리하도록 설계되었다.

그러나 직렬화된 데이터의 전송 및 검증은 추상화되어 BLE 전송 계층 외부에서 볼 수 없다.

 

모든 데이터 패킷이 WriteWithoutResponse를 사용하여 전송된 경우에도 수신되도록 하려면 DFU 컨트롤러가

Execute 명령을 실행하기 전에 개체의 유효성을 검사하기 위해 CRC(순환 중복 검사)를 수행해야 한다.

반응형
반응형

DFU 프로세스는 신뢰할 수 있는 전송 계층이 사용되는 한 전송에 구애받지 않도록 설계되었다.

DFU 전송 모듈은 각 전송 계층에 대해 구현되어야하는 일반적인 인터페이스를 정의한다.

현재 DFU 전송 모듈은 BLE, UART 및 USB CDC 전송을 지원한다.

 

전송 계층을 등록하려면 nrf_dfu_transport_t 등록 구조체를 매개변수로 사용하여 매크로 DFU_TRANSPORT_REGISTER를 호출한다. nrf_dfu_transports_init이 호출되면 등록된 모든 전송 계층이 각각의 초기화 함수로 초기화된다.(nrf_dfu_transport_t::init_func에 정의됨).

 

전송 계층 구현은 nrf_dfu_req_handler_on_req를 호출하여 애플리케이션에 DFU 요청을 전달하는 역할을 한다.

이 함수는 nrf_dfu_request_t유형의 요청을 받아 nrf_dfu_result_t유형의 응답 코드와 함께 nrf_dfu_response_t유형의

응답을 반환한다.

 

다음 표는 요청(nrf_dfu_request_t::request 참조) 및 응답(nrf_dfu_response_t 참조) 유형을 보여준다.

Request Opcode Type Parameters Response parameters
Protocol version 0x00 NRF_DFU_OP_PROTOCOL_VERSION None Version
Create 0x01 NRF_DFU_OP_OBJECT_CREATE Object type
Object size
None
Set receipt notification 0x02 NRF_DFU_OP_RECEIPT_NOTIF_SET Target value None
CRC 0x03 NRF_DFU_OP_CRC_GET None Offset
CRC
Execute 0x04 NRF_DFU_OP_OBJECT_EXECUTE None None
Select 0x06 NRF_DFU_OP_OBJECT_SELECT Object type Offset
CRC
Maximum object size
MTU Get 0x07 NRF_DFU_OP_MTU_GET None Size
Write 0x08 NRF_DFU_OP_OBJECT_WRITE Request payload
Request length
The length must be word-aligned.
None or CRC Response
Ping 0x09 NRF_DFU_OP_PING ID ID
HW Version Get 0x0A NRF_DFU_OP_HARDWARE_VERSION None Part
Variant 
nrf_dfu_response_hardware_t::memory "ROM size" 
nrf_dfu_response_hardware_t::memory "ROM page size" 
nrf_dfu_response_hardware_t::memory "RAM size"
FW Version Get 0x0B NRF_DFU_OP_FIRMWARE_VERSION Image number Type
Version Start address Size
Abort 0x0C NRF_DFU_OP_ABORT None None

1. Requests

nrf_dfu_req_handler_on_req를 호출하여 요청을 하면 nrf_dfu_result_t 유형의 결과 코드가 반환된다.

DFU 요청이 성공적으로 처리되면 결과 코드는 NRF_DFU_RES_CODE_SUCCESS이다.

가능한 오류 코드는 요청의 종류에 따라 다르다.

자세한 내용은 다음의 섹션을 참조한다. 여러 오류가 발생하면 하나의 오류 코드만 반환된다.

1.1 Protocol Version

이 명령의 Syntax와 ID는 영구적이다. 프로토콜 버전이 변경되면 다른 opcode가 더이상 유효하지 않을 수 있다.

이 명령은 선택사항이다.(NRF_DFU_PROTOCOL_VERSION_MSG)

1.2 Create request

Create 요청은 지정된 유형의 객체 생성을 트리거한다.

유효한 유형은 명령 개체(예:초기화 패킷) 또는 개체이다.

 

Create 요청에는 DFU 대상에서 다음 작업이 필요하다.

  • 개체를 위한 공간 예약
  • 마지막 실행 명령 이후의 진행률 재설정
  • 새 개체 선택

이러한 작업 중 하나라도 실패하면 다음 오류 코드 중 하나가 반환되어야 한다.

Error condition Response code
지정된 개체 유형이 지원되지 않음 NRF_DFU_RES_CODE_UNSUPPORTED_TYPE
지정된 크기가 0 NRF_DFU_RES_CODE_INVALID_PARAMETER
데이터 개체에 대해 지정된 크기가 페이지 정렬 되지 않았으며 마지막 개체도 아님  NRF_DFU_RES_CODE_INVALID_PARAMETER
DFU 대상은 지정된 크기의 개체를 허용할 수 없음 NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES
전송의 현재 상태는 주어진 크기와 유형의 개체를 만드는 것을 허용하지 않음 NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED
진행 상황을 Reset할 수 없음 NRF_DFU_RES_CODE_OPERATION_FAILED

1.3 Set receipt notification

이 요청은 Write request 명령 이후 CRC응답을 보내는 빈도를 구성한다.

0으로 설정하면 Write request 후에 CRC응답이 전송되지 않는다.

그렇지 않으면 n번째 Write request마다 전송된다.

여기서 n은 nrf_dfu_request_prn_t::target이다.

1.4 CRC request

CRC 요청은 현재 개체의 전송된 데이터의 오프셋 및 CRC보고를 해야한다.

DFU 컨트롤러는 데이터가 올바르게 전송되었는지 확인하기 위해 이러한 값을 정기적으로 확인해야 한다.

작업이 실패하면 다음 오류 코드가 반환되어야 한다.

Error condition Response code
현재 선택한 개체의 개체 유형이 잘못되었음. NRF_DFU_RES_CODE_INVALID_OBJECT

1.5 Execute request

개체가 완전히 작성된 후에 Execute 요청이 되어야 한다.

요청된 작업은 전송된 개체의 유형에 따라 다르다.

펌웨어 이미지의 모든 개체가 전송되면 사후 검증이 호출된다.

사후 검증이 성공하면 수신된 펌웨어 이미지의 활성화를 트리거한다.

작업 중 하나가 실패하면 다음 오류 코드 중 하나가 반환되어야 한다.

Error condition Response code
현재 선택한 개체의 개체 유형이 잘못됨. NRF_DFU_RES_CODE_INVALID_OBJECT
전송의 현재 상태는 현재 개체의 실행을 허용하지 않음. NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED

1.6 Select request

Select 요청은 지정된 개체 유형의 마지막으로 전송된 개체를 현재 활성 개체로 만든다.

또한 개체에 대한 정보(최대 크기, 현재 오프셋 및 현재 CRC)를 요청한다.

해당 유형의 유효한 개체가 없으면 개체 유형이 계속 선택된다.

이 경우 반환된 CRC와 오프셋은 0이다.

1.7 MTU Get request

전송은 이 요청에 대해 기본 MTU 크기를 반환한다.

1.8 Write request

Write 요청은 수신된 데이터를 장치에 저장하도록 한다. 데이터 작성 방법은 현재 선택한 개체의 유형에 따라 다르다.

수신된 데이터를 저장한 후 DFU 대상은 CRC응답으로 응답할 수 있는 새 CRC 및 오프셋을 계산해야 한다. 

(Set receipt notification 참조)

작업 중 하나가 실패하면 다음 오류 코드 중 하나가 반환되어야 한다.

Error condition Response code
현재 선택한 개체의 개체 유형이 잘못됨. NRF_DFU_RES_CODE_INVALID_OBJECT
전송의 현재 상태는 현재 개체에 대한 쓰기를 허용하지 않음. NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED
지정된 크기는 0. NRF_DFU_RES_CODE_INVALID_PARAMETER
지정된 크기가 너무 큼. NRF_DFU_RES_CODE_INVALID_PARAMETER

1.9 Ping

DFU 대상은 Ping 요청에서 수신한 것과 동일한 ID값으로 응답한다.

1.10 Hardware version

DFU 대상은 Hardware version 세부 정보가 포함된 메세지로 응답한다.

1.11 Firmware version

DFU 대상은 요청된 펌웨어의 유형 및 버전이 포함된 메세지로 응답한다. 펌웨어는 ID로 식별된다.

Firmware ID
Bootloader 0
SoftDevice 1
Application 2(SoftDevice가 없는 경우 1)

지정된 ID의 펌웨어가 없으면 응답에 NRF_DFU_FIRMWARE_TYPE_UNKNOWN 유형이 포함된다.

이 명령은 선택 사항이다.(NRF_DFU_PROTOCOL_FW_VERSION_MSG)

1.11 Abort

현재 DFU 프로세스를 중단한다. 부트로더는 해당 메세지에서 Reset된다.

2. Transport layers

다음 전송 계층을 사용할 수 있다.

 

 

반응형
반응형

DFU에는 개인키와 공개키가 필요하다.

공개키는 개인키로 계산할 수 있지만 개인키는 항상 제공되어야 한다.

 

여러 장치에서 사용할 고정키가 필요한 경우 외부에서 키를 생성해야 한다.

다음 예제 명령은 Nordic Semiconductor의 nrfutil 도구(nrfutil documentation참조)를 사용하여

secp256r1 곡선을 기반으로 키를 생성한다.

# Generate a private key in c:\vault\priv.pem
nrfutil keys generate c:\vault\priv.pem
# Display the generated private key (in little-endian format)
nrfutil keys display --key sk --format hex c:\vault\priv.pem
# Display the public key that corresponds to the generated private key
# (in little-endian format)
nrfutil keys display --key pk --format hex c:\vault\priv.pem
# Display the public key that corresponds to the generated private key
# (in code format to be used with DFU)
nrfutil keys display --key pk --format code c:\vault\priv.pem
# Write the public key that corresponds to the generated private key
# to the file public_key.c (in code format)
nrfutil keys display --key pk --format code c:\vault\priv.pem --out_file public_key.c

OpenSSL 또는 Cryptography library - nrf_crypto를 사용하여 키를 생성할 수도 있다.

둘 다 Big-endian 형식으로 키를 생성한다. 이러한 키를 DFU와 함께 사용하려면 바이트 순서를 반대로 해야한다.

OpenSSL 및 Cryptography library - nrf_crypto를 모두 사용하여 키 쌍을 생성하는 방법에 대한 지침은

Code examples참조한다.

반응형
반응형

장치 펌웨어 업데이트를 안전하게 수행하기 위해 새 펌웨어 이미지가 검증될 때까지

메모리의 최종 위치에 복사되지 않는다. 이렇게 하면 완전하고 유효한 이미지만 활성화된다.

전송중에 오류가 발생하면 펌웨어가 업데이트되지 않고 이전 펌웨어를 계속 사용할 수 있다.

 

수신된 펌웨어를 여유 메모리에 저장한 다음 활성화하는 동안 의도한 메모리 위치에 복사하는

이 프로세스를 이중 뱅크 업데이트라고 한다. 이중 뱅크 업데이트는 새 펌웨어가 확인되고 활성화

될 때까지 현재 응용 프로그램이 유지되기 때문에 선호되는 펌웨어 업데이트 방법이다.

 

이중 뱅크 업데이트는 현재 어플리케이션의 끝과 어플리케이션 데이터의 시작 사이에 새 펌웨어 이미지를

저장할 충분한 여우 공간이 있는 경우에만 가능하다. 새 펌웨어 이미지가 사용 가능한 공간보다 큰 경우

단일 뱅크 업데이트로 전송해야 한다. 이 과정에서 펌웨어 이미지가 기존 어플리케이션을 덮어 쓴다.

단일 뱅크 업데이트 중에 오류가 발생하면 장치에 유효한 어플리케이션이 남지 않는다. 

이 경우 장치는 부트로더에서 DFU 모드를 유지하고 펌웨어 업데이트 프로세스를 다시 시도할 수 있다.

 

NRF_DFU_SINGLE_BANK_APP_UPDATES가 설정된 경우 단일 뱅크 업데이트로 우선적으로 수행된다.

그렇지 않으면 모든 펌웨어 업데이트가 이중 뱅크 업데이트로 수행된다. 그러나 새 이미지(SoftDevice, 

SoftDevice 및 부트로더 또는 어플리케이션)가 사용 가능한 공간보다 큰 경우 펌웨어 이미지를 위한 공간을

만들기 위해 어플리케이션이 삭제되고 단일 뱅크 업데이트가 수행된다.

 

안전상의 이유로 DFU 구성에서 단일 뱅크 업데이트를 비활성화할 수 있다.(NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES참조) 그러나 단일 뱅크 업데이트를 비활성화하면

어플리케이션과 예약된 어플리케이션 데이터 사이의 여유 페이지로 업데이트할 수 있는 크기가 제한된다.

이 여유 공간은 SoftDevice와 부트로더를 결합한 업데이트에 충분하지 않을 수 있다.

1. Dual-bank updates

이중 뱅크 업데이트 중에는 새 펌웨어 이미지가 활성화 될 때까지 기존 어플리케이션이 유지된다.

펌웨어 업데이트 프로세스가 실패하더라도 장치를 재부팅하여 기존 어플리케이션을 시작할 수 있다.

 

SoftDevice의 끝과 어플리케이션 데이터의 시작 사이 메모리영역은 두 개의 뱅크로 나누어진다.

Bank0은 기존 어플리케이션을 보유하고 Bank1은 수신된 이미지를 저장하는데 사용된다.

1.1 SoftDevice and bootloader

다음 그림은 부트로더와 SoftDevice가 결합된 이미지에 대한 DFU 프로세스를 보여준다.

전송된 이미지에 SoftDevice 또는 부트로더만 포함된 경우 일반 프로세스는 동일하지만

SoftDevice 또는 부트로더만 교체된다.

전송된 이미지는 여유 메모리 영역에 저장된다. 기존 어플리케이션 데이터를 유지할 수 있다.

자세한 내용은 Preserving application data을 참조한다. 유효성 검사 후 새 SoftDevice 및

새 부트로더가 복사되어 기존 펌웨어를 대체한다.

어플리케이션은 이 프로세스동안 유지되지만 SoftDevice의 API변경 또는 새 SoftDevice의 크기가

기존 것과 다르기 때문에 유효하지 않을 수 있다.

1.2 Application

이중 뱅크 업데이트에서 어플리케이션을 업데이트할 때 기존 어플리케이션은 유지된다.

원본 어플리케이션은 메모리 Bank0에 있다. 전송된 이미지는 Bank1에 저장된다. 새 어플리케이션 이미지가

수신된 후 이전 어플리케이션과 새 어플리케이션이 모두 존재한다.

이렇게하면 새 어플리케이션을 활성화할 수 없는 경우 이전 어플리케이션으로 대체할 수 있다.

새 어플리케이션을 활성화 할 수 있으면 Bank1에서 Bank0으로 복사된다.

기존 어플리케이션 데이터는 유지할 수 있다. 자세한 내용은 Preserving application data을 참조한다.

2. Single-bank updates

단일 뱅크 업데이트에서는 기존 어플리케이션이 새 펌웨어 이미지로 대체된다.

오류가 발생하고 장치에 유효한 어플리케이션이 없으면 시스템이 DFU모드로 돌아가고 업데이트

프로세스를 다시 시작할 수 있다.

 

DFU부트로더는 이중 뱅크 업데이트가 가능한지 확인한다.

그렇지 않은 경우에만(여유 메모리가 충분하지 않기 때문에) 단일 뱅크 업데이트로 되돌아간다.

 

기존 어플리케이션 데이터를 유지할 수 있다. 자세한 내용은 Preserving application data을 참조한다.

2.1 SoftDevice and bootloader

다음 그림은 단일 뱅크 모드의 어플리케이션에 대한 DFU 프로세스를 보여준다.

새 펌웨어 이미지를 위한 공간을 만들기 위해 기존 어플리케이션이 지워진다. 유효성 검사 후 새 SoftDevice 및 

새 부트로더가 복사되어 기존 펌웨어를 대체한다. 마지막으로 장치가 다시 시작되고 DFU 모드로 들어간다.

(장치에 유효한 어플리케이션이 없기 때문에)

2.2 Application

다음 그림은 단일 뱅크 모드의 어플리게이션에 대한  DFU 프로세스를 보여준다.

새 어플리케이션 이미지를 위한 공간을 만들기 위해 기존 어플리케이션이 지워진다. 전송이 완료되면 부트로더가

새 어플리케이션의 유효성을 검사한다. 유효한 경우 부트로더가 활성화한다. 유효하지 않으면

부트로더가 Reset되고 DFU 모드에서 시작되며 새 이미지가 업로드 될 깨까지 기다린다.

3. Preserving application data

장치 펌웨어 업데이트 동안 유지해야 하는 어플리케이션 데이터(예:본딩정보, 시스템 속성 또는 어플리케이션이

Reset 되는 동안 보존하려는 데이터)는 부트로더가 시작되기 직전에 어플리케이션과 부트로더 사이의

특정 메모리 영역에 저장해야 한다. 이 SDK에서 제공하는 예제가 Peer Manager 데이터를 저장하는 기본 위치이다.

 

DFU동안 어플리케이션 데이터를 보존하려면 nrf_dfu_types.h에서 DFU_APP_DATA_RESERVED에 대한 값을

구성한다. 기본값은 3이다.

#define DFU_APP_DATA_RESERVED            CODE_PAGE_SIZE * 3

값은 페이지 크기의 배수이어야 한다. 예를 들어 페이지 크기가 0x1000인 경우 0x1000, 0x2000, 0x3000 등이다.

반응형
반응형

장치 펌웨어 업데이트를 수행하기 전에 새 이미지를 확인해야 한다.

일부 정보(예:호환성)는 실제 펌웨어가 전송되기 전에 확인할 수 있다.(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가 초기화 패킷에 설정되어 있으면 예제의 디버그 버전은 버전 유효성 검사를 건너뛴다.

 

이러한 검사는 유효성 검사 모듈에서 구현된다. 확인은 다음 순서로 수행된다.

  1. Signature of the packet (signature)
    서명을 확인할 수 있으려면 유효성 검사 코드에 초기화 패킷에 서명하는데 사용된 개인 키에
    해당하는 공개키가 필요하다. 이 키는 dfu_public_key.c 파일에 있다.
  2. Firmware type (fw_type)
    NRF_DFU_APP_DOWNGRADE_PREVENTION구성으로 버전 확인을 활성화/비활성화할 수 있다.
  3. Hardware version (hw_version)
  4. SoftDevice version (sd_req)
  5. Firmware version (fw_version)
  6. 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의 영향을 받지 않는다.

반응형

+ Recent posts