[ion] Encode the serial number in Base64

Also, expose serialNumber() in Ion and keep "copySerialNumber" in
Ion::Device. This allows the DFU bootloader to remain .bss-free.
This commit is contained in:
Romain Goyet
2018-05-04 17:06:16 +02:00
committed by Ecco
parent 11ae2da6c5
commit a29c775663
14 changed files with 90 additions and 47 deletions

View File

@@ -10,9 +10,7 @@ SerialNumberController::SerialNumberController(Responder * parentResponder) :
}
void SerialNumberController::viewWillAppear() {
static char serialNumber[24];
Ion::getSerialNumber(serialNumber);
m_barCodeView.setData(serialNumber);
m_barCodeView.setData(Ion::serialNumber());
}
bool SerialNumberController::handleEvent(Ion::Events::Event event) {

View File

@@ -192,24 +192,13 @@ void SubController::willDisplayCellForIndex(HighlightCell * cell, int index) {
}
if (m_messageTreeModel->label() == I18n::Message::About) {
myCell->setMessageFontSize(KDText::FontSize::Small);
const char * accessoryMessage = nullptr;
char serialNumber[Ion::SerialNumberLength+1];
switch (index) {
case 0:
accessoryMessage = Ion::softwareVersion();
break;
case 1:
Ion::getSerialNumber(serialNumber);
accessoryMessage = serialNumber;
break;
case 2:
accessoryMessage = Ion::fccId();
break;
default:
assert(false);
break;
}
myCell->setAccessoryText(accessoryMessage);
const char * messages[] = {
Ion::softwareVersion(),
Ion::serialNumber(),
Ion::fccId()
};
assert(index >= 0 && index < 3);
myCell->setAccessoryText(messages[index]);
}
}

View File

@@ -28,8 +28,7 @@ namespace Ion {
void msleep(long ms);
void usleep(long us);
constexpr static int SerialNumberLength = 24;
void getSerialNumber(char * buffer);
const char * serialNumber();
const char * softwareVersion();
const char * patchLevel();
const char * fccId();

View File

@@ -15,6 +15,7 @@ objs += $(addprefix ion/src/shared/, \
objs += $(addprefix ion/src/device/, \
backlight.o \
battery.o\
base64.o\
console.o \
device.o\
display.o\

48
ion/src/device/base64.cpp Normal file
View File

@@ -0,0 +1,48 @@
namespace Base64 {
static constexpr char encodeTable[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/',
};
constexpr char Padding = '=';
void encode(const unsigned char * input, unsigned int inputLength, char * output) {
unsigned int i, j;
for (i = j = 0; i < inputLength; i++) {
int s = i % 3; /* from 6/gcd(6, 8) */
switch (s) {
case 0:
output[j++] = encodeTable[(input[i] >> 2) & 0x3F];
continue;
case 1:
output[j++] = encodeTable[((input[i-1] & 0x3) << 4) + ((input[i] >> 4) & 0xF)];
continue;
case 2:
output[j++] = encodeTable[((input[i-1] & 0xF) << 2) + ((input[i] >> 6) & 0x3)];
output[j++] = encodeTable[input[i] & 0x3F];
}
}
/* move back */
i -= 1;
/* check the last and add padding */
if ((i % 3) == 0) {
output[j++] = encodeTable[(input[i] & 0x3) << 4];
output[j++] = Padding;
output[j++] = Padding;
} else if ((i % 3) == 1) {
output[j++] = encodeTable[(input[i] & 0xF) << 2];
output[j++] = Padding;
}
}
}

5
ion/src/device/base64.h Normal file
View File

@@ -0,0 +1,5 @@
namespace Base64 {
void encode(const unsigned char * input, unsigned int inputLength, char * output);
}

View File

@@ -1,5 +1,6 @@
#include "command.h"
#include <ion.h>
#include "../../device.h"
namespace Ion {
namespace Device {
@@ -11,8 +12,8 @@ void MCUSerial(const char * input) {
reply(sSyntaxError);
return;
}
char response[11+Ion::SerialNumberLength + 1] = {'M', 'C', 'U', '_', 'S', 'E', 'R', 'I', 'A', 'L', '=', 0};
Ion::getSerialNumber(response+11);
char response[11 + Ion::Device::SerialNumberLength + 1] = {'M', 'C', 'U', '_', 'S', 'E', 'R', 'I', 'A', 'L', '=', 0};
Ion::Device::copySerialNumber(response + 11);
reply(response);
}

View File

@@ -14,6 +14,7 @@ extern "C" {
#include "swd.h"
#include "usb.h"
#include "bench/bench.h"
#include "base64.h"
#define USE_SD_CARD 0
@@ -65,23 +66,18 @@ uint32_t Ion::random() {
return result;
}
static inline char hex(uint8_t d) {
if (d > 9) {
return 'A'+d-10;
}
return '0'+d;
void Ion::Device::copySerialNumber(char * buffer) {
const unsigned char * rawUniqueID = (const unsigned char *)0x1FFF7A10;
Base64::encode(rawUniqueID, 12, buffer);
buffer[SerialNumberLength] = 0;
}
void Ion::getSerialNumber(char * buffer) {
uint8_t * rawUniqueID = (uint8_t *)0x1FFF7A10;
for (int i=0; i<SerialNumberLength/2; i++) {
uint8_t d = *rawUniqueID++;
buffer[2*i] = hex(d >> 4);
buffer[2*i+1] = hex(d & 0xF);
const char * Ion::serialNumber() {
static char serialNumber[Device::SerialNumberLength + 1] = {0};
if (serialNumber[0] == 0) {
Device::copySerialNumber(serialNumber);
}
buffer[SerialNumberLength] = 0;
return serialNumber;
}
// Private Ion::Device methods

View File

@@ -16,6 +16,14 @@ void shutdownPeripherals();
void initClocks();
void shutdownClocks();
/* The serial number is 96 bits long. That's equal to 16 digits in base 64. We
* expose a convenient "copySerialNumber" routine which can be called without
* using a static variable (and therefore without a .bss section). This is used
* in the RAM'ed DFU bootloader. */
constexpr static int SerialNumberLength = 16;
void copySerialNumber(char * buffer);
/* Pin | Role | Mode | Function
* -----+-------------------+-----------------------+----------
* PA0 | Battery sensing | |

View File

@@ -45,6 +45,7 @@ dfu_objs += ion/src/device/usb/boot.o
dfu_objs += ion/src/device/keyboard.o
dfu_objs += ion/src/device/device.o
dfu_objs += ion/src/device/usb.o
dfu_objs += ion/src/device/base64.o
ion/src/device/usb/dfu.elf: LDFLAGS = --gc-sections -T ion/src/device/usb/dfu.ld
ion/src/device/usb/dfu.elf: $(usb_objs) $(dfu_objs)

View File

@@ -9,8 +9,8 @@ namespace USB {
namespace Device {
void Calculator::PollAndReset(bool exitWithKeyboard) {
char serialNumber[Ion::SerialNumberLength+1];
Ion::getSerialNumber(serialNumber);
char serialNumber[Ion::Device::SerialNumberLength+1];
Ion::Device::copySerialNumber(serialNumber);
Calculator c(serialNumber);
/* Leave DFU mode if the Back key is pressed, the calculator unplugged or the

View File

@@ -1,5 +1,5 @@
#include <ion.h>
void Ion::getSerialNumber(char * buffer) {
strlcpy(buffer, "000000000000000000000000", Ion::SerialNumberLength+1);
const char * Ion::serialNumber() {
return "000000000000";
}

View File

@@ -17,6 +17,7 @@ objs += $(addprefix ion/src/shared/, \
dummy/backlight.o \
dummy/battery.o \
dummy/fcc_id.o \
dummy/serial_number.o \
dummy/usb.o \
)

View File

@@ -116,7 +116,3 @@ void Ion::msleep(long ms) {
}
}
}
void Ion::getSerialNumber(char * buffer) {
strlcpy(buffer, "Simulator", Ion::SerialNumberLength+1);
}