1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-07 05:51:38 +00:00

trezorhal: don't parse (image|vendor) headers twice, don't use legacy stm32 names

This commit is contained in:
Pavol Rusnak 2017-04-05 15:10:33 +02:00
parent 3532b266ce
commit fad4b80af8
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
8 changed files with 102 additions and 99 deletions

View File

@ -62,8 +62,8 @@ bool copy_sdcard(void)
FLASH_EraseInitTypeDef EraseInitStruct; FLASH_EraseInitTypeDef EraseInitStruct;
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.NbSectors = 1; EraseInitStruct.NbSectors = 1;
uint32_t SectorError = 0; uint32_t SectorError = 0;
for (int i = 2; i < 12; i++) { for (int i = 2; i < 12; i++) {
@ -96,7 +96,7 @@ bool copy_sdcard(void)
for (int i = 0; i < (HEADER_SIZE + hdr.codelen) / SDCARD_BLOCK_SIZE; i++) { for (int i = 0; i < (HEADER_SIZE + hdr.codelen) / SDCARD_BLOCK_SIZE; i++) {
sdcard_read_blocks((uint8_t *)buf, i, 1); sdcard_read_blocks((uint8_t *)buf, i, 1);
for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) { for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) {
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, LOADER_START + i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]) != HAL_OK) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, LOADER_START + i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]) != HAL_OK) {
BOOTLOADER_PRINTLN("copy failed"); BOOTLOADER_PRINTLN("copy failed");
sdcard_power_off(); sdcard_power_off();
HAL_FLASH_Lock(); HAL_FLASH_Lock();
@ -116,8 +116,15 @@ bool copy_sdcard(void)
void check_and_jump(void) void check_and_jump(void)
{ {
BOOTLOADER_PRINTLN("checking loader"); BOOTLOADER_PRINTLN("checking loader");
if (image_check_signature((const uint8_t *)LOADER_START, NULL)) {
BOOTLOADER_PRINTLN("valid loader image"); image_header hdr;
if (!image_parse_header((const uint8_t *)LOADER_START, &hdr)) {
BOOTLOADER_PRINTLN("invalid loader header");
return;
}
if (image_check_signature((const uint8_t *)LOADER_START, &hdr, NULL)) {
BOOTLOADER_PRINTLN("valid loader signature");
// TODO: remove debug wait // TODO: remove debug wait
BOOTLOADER_PRINTLN("waiting 1 second"); BOOTLOADER_PRINTLN("waiting 1 second");
HAL_Delay(1000); HAL_Delay(1000);
@ -125,7 +132,7 @@ void check_and_jump(void)
BOOTLOADER_PRINTLN("JUMP!"); BOOTLOADER_PRINTLN("JUMP!");
jump_to(LOADER_START + HEADER_SIZE); jump_to(LOADER_START + HEADER_SIZE);
} else { } else {
BOOTLOADER_PRINTLN("invalid loader image"); BOOTLOADER_PRINTLN("invalid loader signature");
} }
} }

View File

@ -115,14 +115,14 @@ void display_set_orientation(int degrees)
void display_set_backlight(int val) void display_set_backlight(int val)
{ {
__HAL_TIM_SetCompare(&TIM1_Handle, TIM_CHANNEL_1, LED_PWM_TIM_PERIOD * val / 255); __HAL_TIM_SET_COMPARE(&TIM1_Handle, TIM_CHANNEL_1, LED_PWM_TIM_PERIOD * val / 255);
} }
int display_init(void) { int display_init(void) {
// init peripherials // init peripherials
__GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE();
__TIM1_CLK_ENABLE(); __HAL_RCC_TIM1_CLK_ENABLE();
__FSMC_CLK_ENABLE(); __HAL_RCC_FSMC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
@ -130,7 +130,7 @@ int display_init(void) {
GPIO_InitStructure.Pin = GPIO_PIN_14; GPIO_InitStructure.Pin = GPIO_PIN_14;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
@ -138,13 +138,13 @@ int display_init(void) {
GPIO_InitStructure.Pin = GPIO_PIN_12; GPIO_InitStructure.Pin = GPIO_PIN_12;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
// LCD_PWM/PB13 // LCD_PWM/PB13
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF1_TIM1; GPIO_InitStructure.Alternate = GPIO_AF1_TIM1;
GPIO_InitStructure.Pin = GPIO_PIN_13; GPIO_InitStructure.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);

View File

@ -16,8 +16,9 @@ void pendsv_isr_handler(void) {
__fatal_error("pendsv"); __fatal_error("pendsv");
} }
void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len) void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, uint32_t fw_version)
{ {
(void)fw_version;
display_clear(); display_clear();
if (memcmp(vimg, "TOIf", 4) != 0) { if (memcmp(vimg, "TOIf", 4) != 0) {
return; return;
@ -42,19 +43,24 @@ void check_and_jump(void)
LOADER_PRINTLN("invalid vendor header"); LOADER_PRINTLN("invalid vendor header");
return; return;
} }
if (!vendor_check_signature((const uint8_t *)(FIRMWARE_START))) { if (!vendor_check_signature((const uint8_t *)(FIRMWARE_START), &vhdr)) {
LOADER_PRINTLN("unsigned vendor header"); LOADER_PRINTLN("unsigned vendor header");
return; return;
} }
if (image_check_signature((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), &vhdr)) { image_header hdr;
LOADER_PRINTLN("valid firmware image"); if (!image_parse_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), &hdr)) {
display_vendor(vhdr.vimg, (const char *)vhdr.vstr, vhdr.vstr_len); LOADER_PRINTLN("invalid firmware header");
return;
}
if (image_check_signature((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen), &hdr, &vhdr)) {
LOADER_PRINTLN("valid firmware signature");
display_vendor(vhdr.vimg, (const char *)vhdr.vstr, vhdr.vstr_len, hdr.version);
HAL_Delay(1000); // TODO: remove? HAL_Delay(1000); // TODO: remove?
LOADER_PRINTLN("JUMP!"); LOADER_PRINTLN("JUMP!");
jump_to(FIRMWARE_START + vhdr.hdrlen + HEADER_SIZE); jump_to(FIRMWARE_START + vhdr.hdrlen + HEADER_SIZE);
} else { } else {
LOADER_PRINTLN("invalid firmware image"); LOADER_PRINTLN("invalid firmware signature");
} }
} }

View File

@ -6,38 +6,6 @@
#include "common.h" #include "common.h"
#include "image.h" #include "image.h"
bool image_parse_header(const uint8_t *data, image_header *header)
{
if (!header) {
image_header h;
header = &h;
}
memcpy(&header->magic, data, 4);
if (header->magic != IMAGE_MAGIC) return false;
memcpy(&header->hdrlen, data + 4, 4);
if (header->hdrlen != HEADER_SIZE) return false;
memcpy(&header->expiry, data + 8, 4);
if (header->expiry != 0) return false;
memcpy(&header->codelen, data + 12, 4);
if (header->hdrlen + header->codelen < 4 * 1024) return false;
if (header->hdrlen + header->codelen > IMAGE_MAXSIZE) return false;
if ((header->hdrlen + header->codelen) % 512 != 0) return false;
memcpy(&header->version, data + 16, 4);
// uint8_t reserved[427];
memcpy(&header->sigmask, data + 0x01BF, 1);
memcpy(header->sig, data + 0x01C0, 64);
return true;
}
static const uint8_t * const SATOSHILABS_PUBKEYS[] = { static const uint8_t * const SATOSHILABS_PUBKEYS[] = {
(const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d", (const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d",
(const uint8_t *)"\x21\x52\xf8\xd1\x9b\x79\x1d\x24\x45\x32\x42\xe1\x5f\x2e\xab\x6c\xb7\xcf\xfa\x7b\x6a\x5e\xd3\x00\x97\x96\x0e\x06\x98\x81\xdb\x12", (const uint8_t *)"\x21\x52\xf8\xd1\x9b\x79\x1d\x24\x45\x32\x42\xe1\x5f\x2e\xab\x6c\xb7\xcf\xfa\x7b\x6a\x5e\xd3\x00\x97\x96\x0e\x06\x98\x81\xdb\x12",
@ -83,13 +51,40 @@ static bool compute_pubkey(const vendor_header *vhdr, uint8_t sigmask, ed25519_p
return 0 == ed25519_cosi_combine_publickeys(res, keys, vsig_m); return 0 == ed25519_cosi_combine_publickeys(res, keys, vsig_m);
} }
bool image_check_signature(const uint8_t *data, const vendor_header *vhdr) bool image_parse_header(const uint8_t *data, image_header *hdr)
{ {
image_header hdr; if (!hdr) {
if (!image_parse_header(data, &hdr)) { image_header h;
return false; hdr = &h;
} }
memcpy(&hdr->magic, data, 4);
if (hdr->magic != IMAGE_MAGIC) return false;
memcpy(&hdr->hdrlen, data + 4, 4);
if (hdr->hdrlen != HEADER_SIZE) return false;
memcpy(&hdr->expiry, data + 8, 4);
if (hdr->expiry != 0) return false;
memcpy(&hdr->codelen, data + 12, 4);
if (hdr->hdrlen + hdr->codelen < 4 * 1024) return false;
if (hdr->hdrlen + hdr->codelen > IMAGE_MAXSIZE) return false;
if ((hdr->hdrlen + hdr->codelen) % 512 != 0) return false;
memcpy(&hdr->version, data + 16, 4);
// uint8_t reserved[427];
memcpy(&hdr->sigmask, data + 0x01BF, 1);
memcpy(hdr->sig, data + 0x01C0, 64);
return true;
}
bool image_check_signature(const uint8_t *data, const image_header *hdr, const vendor_header *vhdr)
{
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
BLAKE2S_CTX ctx; BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
@ -97,77 +92,72 @@ bool image_check_signature(const uint8_t *data, const vendor_header *vhdr)
for (int i = 0; i < 65; i++) { for (int i = 0; i < 65; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
} }
blake2s_Update(&ctx, data + HEADER_SIZE, hdr.codelen); blake2s_Update(&ctx, data + HEADER_SIZE, hdr->codelen);
blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH);
ed25519_public_key pub; ed25519_public_key pub;
if (!compute_pubkey(vhdr, hdr.sigmask, pub)) return false; if (!compute_pubkey(vhdr, hdr->sigmask, pub)) return false;
return 0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)hdr.sig); return 0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)hdr->sig);
} }
bool vendor_parse_header(const uint8_t *data, vendor_header *header) bool vendor_parse_header(const uint8_t *data, vendor_header *vhdr)
{ {
if (!header) { if (!vhdr) {
vendor_header h; vendor_header h;
header = &h; vhdr = &h;
} }
memcpy(&header->magic, data, 4); memcpy(&vhdr->magic, data, 4);
if (header->magic != 0x565A5254) return false; // TRZV if (vhdr->magic != 0x565A5254) return false; // TRZV
memcpy(&header->hdrlen, data + 4, 4); memcpy(&vhdr->hdrlen, data + 4, 4);
memcpy(&header->expiry, data + 8, 4); memcpy(&vhdr->expiry, data + 8, 4);
if (header->expiry != 0) return false; if (vhdr->expiry != 0) return false;
memcpy(&header->version, data + 12, 2); memcpy(&vhdr->version, data + 12, 2);
memcpy(&header->vsig_m, data + 14, 1); memcpy(&vhdr->vsig_m, data + 14, 1);
memcpy(&header->vsig_n, data + 15, 1); memcpy(&vhdr->vsig_n, data + 15, 1);
for (int i = 0; i < header->vsig_n; i++) { for (int i = 0; i < vhdr->vsig_n; i++) {
header->vpub[i] = data + 16 + i * 32; vhdr->vpub[i] = data + 16 + i * 32;
} }
for (int i = header->vsig_n; i < 8; i++) { for (int i = vhdr->vsig_n; i < 8; i++) {
header->vpub[i] = 0; vhdr->vpub[i] = 0;
} }
memcpy(&header->vstr_len, data + 16 + header->vsig_n * 32, 1); memcpy(&vhdr->vstr_len, data + 16 + vhdr->vsig_n * 32, 1);
header->vstr = data + 16 + header->vsig_n * 32 + 1; vhdr->vstr = data + 16 + vhdr->vsig_n * 32 + 1;
header->vimg = data + 16 + header->vsig_n * 32 + 1 + header->vstr_len; vhdr->vimg = data + 16 + vhdr->vsig_n * 32 + 1 + vhdr->vstr_len;
// align to 4 bytes // align to 4 bytes
header->vimg += (-(uintptr_t)header->vimg) & 3; vhdr->vimg += (-(uintptr_t)vhdr->vimg) & 3;
// uint8_t reserved[427]; // uint8_t reserved[427];
memcpy(&header->sigmask, data + header->hdrlen - 65, 1); memcpy(&vhdr->sigmask, data + vhdr->hdrlen - 65, 1);
memcpy(header->sig, data + header->hdrlen - 64, 64); memcpy(vhdr->sig, data + vhdr->hdrlen - 64, 64);
return true; return true;
} }
bool vendor_check_signature(const uint8_t *data) bool vendor_check_signature(const uint8_t *data, const vendor_header *vhdr)
{ {
vendor_header hdr;
if (!vendor_parse_header(data, &hdr)) {
return false;
}
uint8_t hash[BLAKE2S_DIGEST_LENGTH]; uint8_t hash[BLAKE2S_DIGEST_LENGTH];
BLAKE2S_CTX ctx; BLAKE2S_CTX ctx;
blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH);
blake2s_Update(&ctx, data, hdr.hdrlen - 65); blake2s_Update(&ctx, data, vhdr->hdrlen - 65);
for (int i = 0; i < 65; i++) { for (int i = 0; i < 65; i++) {
blake2s_Update(&ctx, (const uint8_t *)"\x00", 1); blake2s_Update(&ctx, (const uint8_t *)"\x00", 1);
} }
blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH);
ed25519_public_key pub; ed25519_public_key pub;
if (!compute_pubkey(NULL, hdr.sigmask, pub)) return false; if (!compute_pubkey(NULL, vhdr->sigmask, pub)) return false;
return 0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)hdr.sig); return 0 == ed25519_sign_open(hash, BLAKE2S_DIGEST_LENGTH, pub, *(const ed25519_signature *)vhdr->sig);
} }

View File

@ -32,12 +32,12 @@ typedef struct {
uint8_t sig[64]; uint8_t sig[64];
} vendor_header; } vendor_header;
bool image_parse_header(const uint8_t *data, image_header *header); bool image_parse_header(const uint8_t *data, image_header *hdr);
bool image_check_signature(const uint8_t *data, const vendor_header *vhdr); bool image_check_signature(const uint8_t *data, const image_header *hdr, const vendor_header *vhdr);
bool vendor_parse_header(const uint8_t *data, vendor_header *header); bool vendor_parse_header(const uint8_t *data, vendor_header *vhdr);
bool vendor_check_signature(const uint8_t *data); bool vendor_check_signature(const uint8_t *data, const vendor_header *vhdr);
#endif #endif

View File

@ -18,7 +18,7 @@ int sdcard_init(void) {
// configure SD GPIO // configure SD GPIO
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF12_SDIO; GPIO_InitStructure.Alternate = GPIO_AF12_SDIO;
GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
@ -28,7 +28,7 @@ int sdcard_init(void) {
// configure the SD card detect pin // configure the SD card detect pin
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Pin = GPIO_PIN_13; GPIO_InitStructure.Pin = GPIO_PIN_13;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
@ -37,7 +37,7 @@ int sdcard_init(void) {
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// enable SDIO clock // enable SDIO clock
__SDIO_CLK_ENABLE(); __HAL_RCC_SDIO_CLK_ENABLE();
// NVIC configuration for SDIO interrupts // NVIC configuration for SDIO interrupts
HAL_NVIC_SetPriority(SDIO_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO); HAL_NVIC_SetPriority(SDIO_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO);
@ -48,7 +48,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
HAL_NVIC_DisableIRQ(SDIO_IRQn); HAL_NVIC_DisableIRQ(SDIO_IRQn);
__SDIO_CLK_DISABLE(); __HAL_RCC_SDIO_CLK_DISABLE();
} }
bool sdcard_is_present(void) { bool sdcard_is_present(void) {

View File

@ -313,7 +313,7 @@ void SystemClock_Config(void)
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
/* Enable Power Control clock */ /* Enable Power Control clock */
__PWR_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE();
/* The voltage scaling allows optimizing the power consumption when the device is /* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value clocked below the maximum system frequency, to update the voltage scaling value
@ -466,7 +466,7 @@ void SystemClock_Config(void)
__fatal_error("HAL_RCCEx_PeriphCLKConfig"); __fatal_error("HAL_RCCEx_PeriphCLKConfig");
} }
__PWR_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE();
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

2
vendor/norcow vendored

@ -1 +1 @@
Subproject commit 5977b17a360df12af82a6c205a052f90e42e7db7 Subproject commit ea6d2d03d07ca9c51ff22a1521ce35dfda9fc12e