Skip to content

Commit

Permalink
Merge branch 'feature/partition_readonly_flag' into 'master'
Browse files Browse the repository at this point in the history
feat(partition_table): Add read-only partition flag and functionality

Closes IDF-6421

See merge request espressif/esp-idf!24855
  • Loading branch information
pacucha42 committed Oct 13, 2023
2 parents ca1cd88 + 37dbce3 commit 64befdc
Show file tree
Hide file tree
Showing 50 changed files with 852 additions and 172 deletions.
12 changes: 11 additions & 1 deletion components/bootloader_support/include/esp_flash_partitions.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -33,6 +33,7 @@ extern "C" {
#define PART_SUBTYPE_END 0xff

#define PART_FLAG_ENCRYPTED (1<<0)
#define PART_FLAG_READONLY (1<<1)

/* The md5sum value is found this many bytes after the ESP_PARTITION_MAGIC_MD5 offset */
#define ESP_PARTITION_MD5_OFFSET 16
Expand Down Expand Up @@ -92,6 +93,15 @@ typedef struct {
*/
esp_err_t esp_partition_table_verify(const esp_partition_info_t *partition_table, bool log_errors, int *num_partitions);

/**
* Check whether the region on the main flash is not read-only.
*
* @param addr Start address of the region
* @param size Size of the region
*
* @return true if the region is safe to write, otherwise false.
*/
bool esp_partition_is_flash_region_writable(size_t addr, size_t size);

/**
* Check whether the region on the main flash is safe to write.
Expand Down
1 change: 1 addition & 0 deletions components/esp_common/include/esp_err.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef int esp_err_t;
#define ESP_ERR_INVALID_VERSION 0x10A /*!< Version was invalid */
#define ESP_ERR_INVALID_MAC 0x10B /*!< MAC address was invalid */
#define ESP_ERR_NOT_FINISHED 0x10C /*!< Operation has not fully completed */
#define ESP_ERR_NOT_ALLOWED 0x10D /*!< Operation is not allowed */


#define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */
Expand Down
3 changes: 3 additions & 0 deletions components/esp_common/src/esp_err_to_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# endif
# ifdef ESP_ERR_NOT_FINISHED
ERR_TBL_IT(ESP_ERR_NOT_FINISHED), /* 268 0x10c Operation has not fully completed */
# endif
# ifdef ESP_ERR_NOT_ALLOWED
ERR_TBL_IT(ESP_ERR_NOT_ALLOWED), /* 269 0x10d Operation is not allowed */
# endif
// components/nvs_flash/include/nvs.h
# ifdef ESP_ERR_NVS_BASE
Expand Down
4 changes: 4 additions & 0 deletions components/esp_partition/include/esp_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ typedef struct {
uint32_t erase_size; /*!< size the erase operation should be aligned to */
char label[17]; /*!< partition label, zero-terminated ASCII string */
bool encrypted; /*!< flag is set to true if partition is encrypted */
bool readonly; /*!< flag is set to true if partition is read-only */
} esp_partition_t;

/**
Expand Down Expand Up @@ -270,6 +271,7 @@ esp_err_t esp_partition_read(const esp_partition_t* partition,
* @return ESP_OK, if data was written successfully;
* ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
* ESP_ERR_NOT_ALLOWED, if partition is read-only;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_write(const esp_partition_t* partition,
Expand Down Expand Up @@ -322,6 +324,7 @@ esp_err_t esp_partition_read_raw(const esp_partition_t* partition,
* @return ESP_OK, if data was written successfully;
* ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
* ESP_ERR_NOT_ALLOWED, if partition is read-only;
* or one of the error codes from lower-level flash driver.
*/
esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
Expand All @@ -341,6 +344,7 @@ esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
* @return ESP_OK, if the range was erased successfully;
* ESP_ERR_INVALID_ARG, if iterator or dst are NULL;
* ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
* ESP_ERR_NOT_ALLOWED, if partition is read-only;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
Expand Down
3 changes: 2 additions & 1 deletion components/esp_partition/partition.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ static esp_err_t load_partitions(void)
item->info.type = entry.type;
item->info.subtype = entry.subtype;
item->info.encrypted = entry.flags & PART_FLAG_ENCRYPTED;
item->info.readonly = entry.flags & PART_FLAG_READONLY;
item->user_registered = false;

#if CONFIG_IDF_TARGET_LINUX
Expand Down Expand Up @@ -349,7 +350,6 @@ const esp_partition_t *esp_partition_find_first(esp_partition_type_t type,
return res;
}


void esp_partition_iterator_release(esp_partition_iterator_t iterator)
{
// iterator == NULL is okay
Expand Down Expand Up @@ -384,6 +384,7 @@ const esp_partition_t *esp_partition_verify(const esp_partition_t *partition)
esp_partition_iterator_release(it);
return NULL;
}

esp_err_t esp_partition_register_external(esp_flash_t *flash_chip, size_t offset, size_t size,
const char *label, esp_partition_type_t type, esp_partition_subtype_t subtype,
const esp_partition_t **out_partition)
Expand Down
6 changes: 6 additions & 0 deletions components/esp_partition/partition_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@ esp_err_t esp_partition_write(const esp_partition_t *partition, size_t dst_offse
{
assert(partition != NULL && s_spiflash_mem_file_buf != NULL);

if (partition->readonly) {
return ESP_ERR_NOT_ALLOWED;
}
if (partition->encrypted) {
return ESP_ERR_NOT_SUPPORTED;
}
Expand Down Expand Up @@ -450,6 +453,9 @@ esp_err_t esp_partition_erase_range(const esp_partition_t *partition, size_t off
{
assert(partition != NULL);

if (partition->readonly) {
return ESP_ERR_NOT_ALLOWED;
}
if (offset > partition->size || offset % partition->erase_size != 0) {
return ESP_ERR_INVALID_ARG;
}
Expand Down
31 changes: 28 additions & 3 deletions components/esp_partition/partition_target.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -64,6 +64,9 @@ esp_err_t esp_partition_write(const esp_partition_t *partition,
size_t dst_offset, const void *src, size_t size)
{
assert(partition != NULL);
if (partition->readonly) {
return ESP_ERR_NOT_ALLOWED;
}
if (dst_offset > partition->size) {
return ESP_ERR_INVALID_ARG;
}
Expand Down Expand Up @@ -103,6 +106,9 @@ esp_err_t esp_partition_write_raw(const esp_partition_t *partition,
size_t dst_offset, const void *src, size_t size)
{
assert(partition != NULL);
if (partition->readonly) {
return ESP_ERR_NOT_ALLOWED;
}
if (dst_offset > partition->size) {
return ESP_ERR_INVALID_ARG;
}
Expand All @@ -118,6 +124,9 @@ esp_err_t esp_partition_erase_range(const esp_partition_t *partition,
size_t offset, size_t size)
{
assert(partition != NULL);
if (partition->readonly) {
return ESP_ERR_NOT_ALLOWED;
}
if (offset > partition->size) {
return ESP_ERR_INVALID_ARG;
}
Expand Down Expand Up @@ -193,9 +202,25 @@ bool esp_partition_check_identity(const esp_partition_t *partition_1, const esp_
return false;
}

bool esp_partition_is_flash_region_writable(size_t addr, size_t size)
{
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
for (; it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *p = esp_partition_get(it);
if (p->readonly) {
if (addr >= p->address && addr < p->address + p->size) {
return false;
}
if (addr < p->address && addr + size > p->address) {
return false;
}
}
}
return true;
}

bool esp_partition_main_flash_region_safe(size_t addr, size_t size)
{
bool result = true;
if (addr <= ESP_PARTITION_TABLE_OFFSET + ESP_PARTITION_TABLE_MAX_LEN) {
return false;
}
Expand All @@ -206,5 +231,5 @@ bool esp_partition_main_flash_region_safe(size_t addr, size_t size)
if (addr < p->address && addr + size > p->address) {
return false;
}
return result;
return true;
}
2 changes: 1 addition & 1 deletion components/fatfs/diskio/diskio_wl.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down
14 changes: 12 additions & 2 deletions components/fatfs/vfs/vfs_fat_spiflash.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -8,7 +8,6 @@
#include <string.h>
#include "esp_check.h"
#include "esp_log.h"
#include "esp_vfs.h"
#include "esp_vfs_fat.h"
#include "vfs_fat_internal.h"
#include "diskio_impl.h"
Expand All @@ -29,6 +28,8 @@ typedef struct vfs_fat_spiflash_ctx_t {

static vfs_fat_spiflash_ctx_t *s_ctx[FF_VOLUMES] = {};

extern esp_err_t esp_vfs_set_readonly_flag(const char* base_path); // from vfs/vfs.c to set readonly flag in esp_vfs_t struct externally

static bool s_get_context_id_by_label(const char *label, uint32_t *out_id)
{
vfs_fat_spiflash_ctx_t *p_ctx = NULL;
Expand Down Expand Up @@ -160,6 +161,10 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path,
assert(ctx_id != FF_VOLUMES);
s_ctx[ctx_id] = ctx;

if (data_partition->readonly) {
esp_vfs_set_readonly_flag(base_path);
}

return ESP_OK;

fail:
Expand Down Expand Up @@ -296,6 +301,11 @@ esp_err_t esp_vfs_fat_spiflash_mount_ro(const char* base_path,
ret = ESP_FAIL;
goto fail;
}

if (data_partition->readonly) {
esp_vfs_set_readonly_flag(base_path);
}

return ESP_OK;

fail:
Expand Down
7 changes: 6 additions & 1 deletion components/nvs_flash/host_test/fixtures/test_fixtures.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -76,6 +76,11 @@ class PartitionMock : public nvs::Partition {
return size;
}

bool get_readonly() override
{
return partition.readonly;
}

const esp_partition_t partition;

private:
Expand Down
2 changes: 2 additions & 0 deletions components/nvs_flash/include/nvs.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ typedef struct nvs_opaque_iterator_t *nvs_iterator_t;
* - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures
* - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is no space for a new entry or there are too many different
* namespaces (maximum allowed different namespaces: 254)
* - ESP_ERR_NOT_ALLOWED if the NVS partition is read-only and mode is NVS_READWRITE
* - other error codes from the underlying storage driver
*/
esp_err_t nvs_open(const char* namespace_name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle);
Expand Down Expand Up @@ -166,6 +167,7 @@ esp_err_t nvs_open(const char* namespace_name, nvs_open_mode_t open_mode, nvs_ha
* - ESP_ERR_NO_MEM in case memory could not be allocated for the internal structures
* - ESP_ERR_NVS_NOT_ENOUGH_SPACE if there is no space for a new entry or there are too many different
* namespaces (maximum allowed different namespaces: 254)
* - ESP_ERR_NOT_ALLOWED if the NVS partition is read-only and mode is NVS_READWRITE
* - other error codes from the underlying storage driver
*/
esp_err_t nvs_open_from_partition(const char *part_name, const char* namespace_name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle);
Expand Down
1 change: 1 addition & 0 deletions components/nvs_flash/include/nvs_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class NVSHandle {
* - ESP_ERR_NVS_NOT_FOUND id namespace doesn't exist yet and
* mode is NVS_READONLY
* - ESP_ERR_NVS_INVALID_NAME if namespace name doesn't satisfy constraints
* - ESP_ERR_NOT_ALLOWED if the NVS partition is read-only and mode is NVS_READWRITE
* - other error codes from the underlying storage driver
*
* @return unique pointer of an nvs handle on success, an empty unique pointer otherwise
Expand Down
23 changes: 10 additions & 13 deletions components/nvs_flash/src/nvs_partition.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <cstdlib>
#include "nvs_partition.hpp"
Expand Down Expand Up @@ -74,4 +66,9 @@ uint32_t NVSPartition::get_size()
return mESPPartition->size;
}

bool NVSPartition::get_readonly()
{
return mESPPartition->readonly;
}

} // nvs
7 changes: 6 additions & 1 deletion components/nvs_flash/src/nvs_partition.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -99,6 +99,11 @@ class NVSPartition : public Partition, public intrusive_list_node<NVSPartition>,
*/
uint32_t get_size() override;

/**
* @return true if the partition is read-only.
*/
bool get_readonly() override;

protected:
const esp_partition_t* mESPPartition;
};
Expand Down
7 changes: 6 additions & 1 deletion components/nvs_flash/src/nvs_partition_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -192,6 +192,11 @@ esp_err_t NVSPartitionManager::open_handle(const char *part_name,
return ESP_ERR_NVS_PART_NOT_FOUND;
}

if (open_mode == NVS_READWRITE && const_cast<Partition*>(sHandle->getPart())->get_readonly()) {
return ESP_ERR_NOT_ALLOWED;
}


esp_err_t err = sHandle->createOrOpenNamespace(ns_name, open_mode == NVS_READWRITE, nsIndex);
if (err != ESP_OK) {
return err;
Expand Down
23 changes: 10 additions & 13 deletions components/nvs_flash/src/partition.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef PARTITION_HPP_
#define PARTITION_HPP_
Expand Down Expand Up @@ -52,6 +44,11 @@ class Partition {
* Return the partition size in bytes.
*/
virtual uint32_t get_size() = 0;

/**
* Return true if the partition is read-only.
*/
virtual bool get_readonly() = 0;
};

} // nvs
Expand Down
Loading

0 comments on commit 64befdc

Please sign in to comment.