Skip to content

Commit 6f26de1

Browse files
committed
fix: Minor changes and fixes
Will be squashed
1 parent 2c836ab commit 6f26de1

File tree

10 files changed

+149
-56
lines changed

10 files changed

+149
-56
lines changed

esp_ext_part_tables/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ set(srcs "src/esp_ext_part_tables.c"
33

44
idf_component_register(SRCS ${srcs}
55
INCLUDE_DIRS "include"
6+
PRIV_INCLUDE_DIRS "private_include"
67
REQUIRES "log" "esp_common")

esp_ext_part_tables/include/esp_ext_part_tables.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#include <stdint.h>
1010
#include <stdbool.h>
1111
#include <stddef.h>
12-
#include <sys/lock.h>
1312
#include "esp_err.h"
1413

1514
#if __has_include(<bsd/sys/queue.h>)
@@ -37,6 +36,7 @@ typedef enum {
3736

3837
typedef enum {
3938
ESP_EXT_PART_TYPE_UNKNOWN = 0,
39+
ESP_EXT_PART_TYPE_FAT_ANY, /*!< FAT partition (any type) */
4040
ESP_EXT_PART_TYPE_FAT12,
4141
ESP_EXT_PART_TYPE_FAT16, /*!< FAT16 with LBA addressing */
4242
ESP_EXT_PART_TYPE_FAT32, /*!< FAT32 with LBA addressing */
@@ -68,12 +68,12 @@ typedef struct {
6868
} esp_ext_part_list_signature_t;
6969

7070
typedef struct {
71-
uint64_t address;
72-
uint64_t sector_count;
73-
uint32_t extra;
71+
uint64_t address; /*!< Start address in LBA */
72+
uint64_t size; /*!< Size in bytes */
73+
uint32_t extra; /*!< Extra information (e.g. LittleFS block size stored in CHS hack, etc.) */
7474
char* label;
75-
esp_ext_part_flags_t flags;
76-
esp_ext_part_type_known_t type;
75+
esp_ext_part_flags_t flags; /*!< Flags for the partition */
76+
esp_ext_part_type_known_t type; /*!< Known partition type for this component */
7777
} esp_ext_part_t;
7878

7979
typedef struct esp_ext_part_list_item_ {
@@ -83,8 +83,8 @@ typedef struct esp_ext_part_list_item_ {
8383

8484
typedef struct {
8585
esp_ext_part_list_signature_t signature; /*!< Disk signature or identifier */
86-
SLIST_HEAD(esp_ext_part_list_head_, esp_ext_part_list_item_) head;
87-
esp_ext_part_list_flags_t flags;
86+
SLIST_HEAD(esp_ext_part_list_head_, esp_ext_part_list_item_) head; /*!< Head of the partition list */
87+
esp_ext_part_list_flags_t flags; /*!< Flags for the partition list */
8888
esp_ext_part_sector_size_t sector_size; /*!< Sector size (storage medium property) */
8989
} esp_ext_part_list_t;
9090

@@ -168,6 +168,7 @@ esp_err_t esp_ext_part_list_signature_get(esp_ext_part_list_t* part_list, void*
168168
* - ESP_ERR_NOT_SUPPORTED: Unsupported signature type.
169169
*/
170170
esp_err_t esp_ext_part_list_signature_set(esp_ext_part_list_t* part_list, const void* signature, esp_ext_part_signature_type_t type);
171+
171172
#ifdef __cplusplus
172173
}
173174
#endif

esp_ext_part_tables/include/esp_mbr.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,6 @@ typedef struct {
6868
} mbr_t;
6969
#pragma pack(pop)
7070

71-
// Helper functions for MBR CHS conversion and LBA alignment
72-
void mbr_set_chs(uint8_t chs[3], uint32_t val);
73-
uint32_t mbr_get_chs(const uint8_t chs[3]);
74-
void lba_to_chs(uint8_t chs[3], uint32_t lba);
75-
uint32_t lba_align(uint32_t lba, esp_ext_part_sector_size_t sector_size, esp_ext_part_align_t alignment);
76-
7771
typedef struct {
7872
esp_ext_part_sector_size_t sector_size; // Sector size hint, pulled from a storage device driver query
7973
} esp_mbr_parse_extra_args_t;
@@ -126,6 +120,7 @@ esp_err_t esp_mbr_parse(void* mbr_buf,
126120
* - ESP_OK: Generation was successful.
127121
* - ESP_ERR_INVALID_ARG: Invalid arguments were provided.
128122
* - ESP_ERR_INVALID_STATE: Error filling partition entry.
123+
* - ESP_ERR_NOT_SUPPORTED: Partition address or size (sector count) exceeds 32-bit limit of MBR.
129124
* - Other error codes from `esp_ext_part_list_insert` or related routines.
130125
*/
131126
esp_err_t esp_mbr_generate(mbr_t* mbr,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdint.h>
10+
#include "esp_ext_part_tables.h"
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
uint64_t esp_ext_part_bytes_to_sector_count(uint64_t total_bytes, esp_ext_part_sector_size_t sector_size);
17+
18+
uint64_t esp_ext_part_sector_count_to_bytes(uint64_t sector_count, esp_ext_part_sector_size_t sector_size);
19+
20+
#ifdef __cplusplus
21+
}
22+
#endif
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdint.h>
10+
#include "esp_ext_part_tables.h"
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#define MBR_CHS_HEADS 255
17+
#define MBR_CHS_SECTORS_PER_TRACK 63
18+
#define MBR_CHS_MAX_CYLINDER 1023
19+
#define MBR_CHS_MAX_HEAD 254
20+
#define MBR_CHS_MAX_SECTOR 63
21+
22+
// Helper functions for MBR CHS conversion and LBA alignment
23+
void esp_mbr_chs_arr_val_set(uint8_t chs[3], uint32_t val);
24+
25+
uint32_t esp_mbr_chs_arr_val_get(const uint8_t chs[3]);
26+
27+
void esp_mbr_lba_to_chs_arr(uint8_t chs[3], uint32_t lba);
28+
29+
uint32_t esp_mbr_lba_align(uint32_t lba, esp_ext_part_sector_size_t sector_size, esp_ext_part_align_t alignment);
30+
31+
#ifdef __cplusplus
32+
}
33+
#endif

esp_ext_part_tables/src/esp_ext_part_tables.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,34 @@
88
#include <assert.h>
99
#include <string.h>
1010
#include <stdio.h>
11-
#include <sys/lock.h>
11+
#include "freertos/FreeRTOS.h"
12+
#include "freertos/task.h"
1213
#include "esp_err.h"
1314
#include "esp_log.h"
15+
1416
#include "esp_ext_part_tables.h"
17+
#include "esp_ext_part_tables_private.h"
1518

1619
#if __has_include(<bsd/sys/queue.h>)
1720
#include <bsd/sys/queue.h>
1821
#else
1922
#include "sys/queue.h"
2023
#endif
2124

25+
uint64_t esp_ext_part_bytes_to_sector_count(uint64_t total_bytes, esp_ext_part_sector_size_t sector_size)
26+
{
27+
if (sector_size == ESP_EXT_PART_SECTOR_SIZE_UNKNOWN) {
28+
return 0; // Avoid division by zero
29+
}
30+
// Ceiling division for integers: (a + b - 1) / b
31+
return ((total_bytes + (uint64_t) sector_size - 1) / (uint64_t) sector_size);
32+
}
33+
34+
uint64_t esp_ext_part_sector_count_to_bytes(uint64_t sector_count, esp_ext_part_sector_size_t sector_size)
35+
{
36+
return sector_count * (uint64_t) sector_size;
37+
}
38+
2239
esp_err_t esp_ext_part_list_deinit(esp_ext_part_list_t* part_list)
2340
{
2441
if (part_list == NULL) {

esp_ext_part_tables/src/esp_mbr.c

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
#include "esp_err.h"
1212
#include "esp_log.h"
1313
#include "esp_random.h"
14+
1415
#include "esp_ext_part_tables.h"
16+
#include "esp_ext_part_tables_private.h"
1517
#include "esp_mbr.h"
18+
#include "esp_mbr_private.h"
1619

1720
#if __has_include(<bsd/sys/queue.h>)
1821
#include <bsd/sys/queue.h>
@@ -22,25 +25,19 @@
2225

2326
static const char* TAG = "esp_mbr";
2427

25-
#define MBR_CHS_HEADS 255
26-
#define MBR_CHS_SECTORS_PER_TRACK 63
27-
#define MBR_CHS_MAX_CYLINDER 1023
28-
#define MBR_CHS_MAX_HEAD 254
29-
#define MBR_CHS_MAX_SECTOR 63
30-
31-
void mbr_set_chs(uint8_t chs[3], uint32_t val)
28+
void esp_mbr_chs_arr_val_set(uint8_t chs[3], uint32_t val)
3229
{
3330
chs[0] = val & 0xFF;
3431
chs[1] = (val >> 8) & 0xFF;
3532
chs[2] = (val >> 16) & 0xFF;
3633
}
3734

38-
uint32_t mbr_get_chs(const uint8_t chs[3])
35+
uint32_t esp_mbr_chs_arr_val_get(const uint8_t chs[3])
3936
{
4037
return chs[0] | (chs[1] << 8) | (chs[2] << 16);
4138
}
4239

43-
void lba_to_chs(uint8_t chs[3], uint32_t lba)
40+
void esp_mbr_lba_to_chs_arr(uint8_t chs[3], uint32_t lba)
4441
{
4542
uint16_t cylinder;
4643
uint8_t head;
@@ -75,7 +72,7 @@ void lba_to_chs(uint8_t chs[3], uint32_t lba)
7572
}
7673
}
7774

78-
uint32_t lba_align(uint32_t lba, esp_ext_part_sector_size_t sector_size, esp_ext_part_align_t alignment)
75+
uint32_t esp_mbr_lba_align(uint32_t lba, esp_ext_part_sector_size_t sector_size, esp_ext_part_align_t alignment)
7976
{
8077
if (sector_size == 0 || alignment == 0) {
8178
return lba; // No alignment
@@ -93,6 +90,18 @@ static uint8_t ext_part_type_known_to_mbr_type(esp_ext_part_type_known_t type)
9390
return 0x06; // FAT16B with LBA addressing
9491
case ESP_EXT_PART_TYPE_FAT32:
9592
return 0x0C; // FAT32 with LBA addressing
93+
/*
94+
LittleFS is not a standard MBR partition type, but we can use a custom type `0xC3`, which is not usually used nowadays.
95+
This allows us to identify LittleFS partitions in the MBR.
96+
97+
Explanation why `0xC3` was chosen:
98+
0xC 3
99+
1100 0011
100+
↑↑ ↑ ↑↑↑↑
101+
└│─│─┴┴┴┴── 0x83 => a modern filesystem (e.g. Linux)
102+
└─│─────── 0x40 => CHS used as LittleFS block size
103+
└─────── 0x10 => a hidden filesystem
104+
*/
96105
case ESP_EXT_PART_TYPE_LITTLEFS:
97106
return 0xC3; // Possibly LittleFS (MBR CHS field => LittleFS block size hack)
98107
case ESP_EXT_PART_TYPE_EXFAT_OR_NTFS: // Not supported, but we can return a type for it
@@ -173,7 +182,7 @@ static void ext_part_list_item_do_extra(esp_ext_part_list_item_t* item, mbr_part
173182
switch (item->info.type) { // Parsed type
174183
case ESP_EXT_PART_TYPE_LITTLEFS:
175184
item->info.flags |= ESP_EXT_PART_FLAG_EXTRA; // Set the extra flag to indicate that this partition has extra information
176-
item->info.extra = mbr_get_chs(partition->chs_start); // Put LittleFS block size which was stored in `chs_start` to `extra` field
185+
item->info.extra = esp_mbr_chs_arr_val_get(partition->chs_start); // Put LittleFS block size which was stored in `chs_start` to `extra` field
177186
break;
178187
default:
179188
break;
@@ -195,11 +204,13 @@ esp_err_t esp_mbr_parse(void* mbr_buf,
195204
return ESP_ERR_NOT_FOUND;
196205
}
197206

207+
// Set defaults
208+
part_list->sector_size = ESP_EXT_PART_SECTOR_SIZE_512B; // Default sector size
209+
210+
// Load extra arguments if provided
198211
if (extra_args) {
199212
if (extra_args->sector_size != ESP_EXT_PART_SECTOR_SIZE_UNKNOWN) {
200213
part_list->sector_size = extra_args->sector_size; // Use the sector size hint from extra_args
201-
} else {
202-
part_list->sector_size = ESP_EXT_PART_SECTOR_SIZE_512B; // Default sector size
203214
}
204215
}
205216

@@ -240,7 +251,7 @@ esp_err_t esp_mbr_parse(void* mbr_buf,
240251
esp_ext_part_list_item_t item = {
241252
.info = {
242253
.address = partition->lba_start,
243-
.sector_count = partition->sector_count,
254+
.size = esp_ext_part_sector_count_to_bytes((uint64_t) partition->sector_count, part_list->sector_size),
244255
.extra = 0,
245256
.label = NULL, // MBR does not have labels
246257
.flags = ESP_EXT_PART_FLAG_NONE,
@@ -275,14 +286,14 @@ static bool mbr_partition_fill(mbr_partition_t* partition, esp_ext_part_list_ite
275286
case ESP_EXT_PART_TYPE_FAT16:
276287
case ESP_EXT_PART_TYPE_FAT32:
277288
// Set CHS values based on LBA start and end
278-
lba_to_chs(partition->chs_start, lba_start);
279-
lba_to_chs(partition->chs_end, lba_end);
289+
esp_mbr_lba_to_chs_arr(partition->chs_start, lba_start);
290+
esp_mbr_lba_to_chs_arr(partition->chs_end, lba_end);
280291
break;
281292
case ESP_EXT_PART_TYPE_LITTLEFS:
282293
// Use `chs_start` to store LittleFS block size (if stored in `extra` field)
283294
if (item->info.extra != 0) {
284295
// If the extra flag is set, use the extra field to store the LittleFS block size
285-
mbr_set_chs(partition->chs_start, item->info.extra);
296+
esp_mbr_chs_arr_val_set(partition->chs_start, item->info.extra);
286297

287298
if (!(item->info.flags & ESP_EXT_PART_FLAG_EXTRA)) {
288299
// If the extra flag is not set but the extra field is set, log a warning
@@ -307,12 +318,14 @@ esp_err_t esp_mbr_generate(mbr_t* mbr,
307318
return ESP_ERR_INVALID_ARG;
308319
}
309320

321+
// Set default arguments for MBR generation
310322
esp_mbr_generate_extra_args_t args = {
311323
.sector_size = part_list->sector_size != ESP_EXT_PART_SECTOR_SIZE_UNKNOWN ? part_list->sector_size : ESP_EXT_PART_SECTOR_SIZE_512B, // Default sector size
312324
.alignment = ESP_EXT_PART_ALIGN_1MiB, // Default alignment
313325
.keep_signature = false, // Default is to generate a new disk signature
314326
};
315327

328+
// Load extra arguments if provided
316329
if (extra_args) {
317330
if (extra_args->sector_size != ESP_EXT_PART_SECTOR_SIZE_UNKNOWN) {
318331
args.sector_size = extra_args->sector_size;
@@ -342,15 +355,23 @@ esp_err_t esp_mbr_generate(mbr_t* mbr,
342355
mbr_partition_t* partition = NULL;
343356
esp_ext_part_list_item_t *it = NULL;
344357
int i = 0;
358+
uint64_t sector_count;
345359
SLIST_FOREACH(it, &part_list->head, next) {
360+
// Check if we have enough space in the MBR partition table
361+
sector_count = esp_ext_part_bytes_to_sector_count(it->info.size, args.sector_size);
362+
if (it->info.address > UINT32_MAX || sector_count > UINT32_MAX) {
363+
ESP_LOGE(TAG, "Partition address or size exceeds 32-bit limit of MBR");
364+
return ESP_ERR_NOT_SUPPORTED; // Address or size too large for MBR
365+
}
366+
346367
partition = (mbr_partition_t*) &mbr->partition_table[i];
347368
i += 1;
348369

349370
if (it->info.flags & ESP_EXT_PART_FLAG_ACTIVE) {
350371
partition->status = MBR_PARTITION_STATUS_ACTIVE;
351372
}
352-
partition->lba_start = lba_align(it->info.address, args.sector_size, args.alignment);
353-
partition->sector_count = it->info.sector_count;
373+
partition->lba_start = esp_mbr_lba_align((uint32_t) it->info.address, args.sector_size, args.alignment);
374+
partition->sector_count = (uint32_t) sector_count;
354375
partition->type = ext_part_type_known_to_mbr_type(it->info.type);
355376

356377
if (mbr_partition_fill(partition, it) == false) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
idf_component_register(SRC_DIRS "."
2-
PRIV_INCLUDE_DIRS "."
2+
PRIV_INCLUDE_DIRS "." "../../private_include"
33
PRIV_REQUIRES esp_ext_part_tables unity)

0 commit comments

Comments
 (0)