summaryrefslogtreecommitdiff
path: root/zephyr/emul/emul_flash.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/emul/emul_flash.c')
-rw-r--r--zephyr/emul/emul_flash.c192
1 files changed, 149 insertions, 43 deletions
diff --git a/zephyr/emul/emul_flash.c b/zephyr/emul/emul_flash.c
index 2fa88916f3..0efc690fd4 100644
--- a/zephyr/emul/emul_flash.c
+++ b/zephyr/emul/emul_flash.c
@@ -1,10 +1,11 @@
-/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+/* Copyright 2022 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#define DT_DRV_COMPAT cros_ec_flash_emul
+#include <zephyr/drivers/flash.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(emul_flash);
@@ -14,74 +15,183 @@ LOG_MODULE_REGISTER(emul_flash);
#include <drivers/cros_flash.h>
#include <zephyr/sys/__assert.h>
-struct flash_emul_data {};
+#include "flash.h"
+
+struct flash_emul_data {
+ const struct device *flash_dev;
+};
struct flash_emul_cfg {
- /** Label of the device being emulated */
- const char *dev_label;
/** Pointer to run-time data */
struct flash_emul_data *data;
};
-void system_jump_to_booter(void)
-{
-}
+#define FLASH_DEV DT_CHOSEN(zephyr_flash_controller)
-uint32_t system_get_lfw_address(void)
-{
- uint32_t jump_addr = (uint32_t)system_jump_to_booter;
- return jump_addr;
-}
+#define DRV_DATA(dev) ((struct flash_emul_data *)(dev)->data)
-enum ec_image system_get_shrspi_image_copy(void)
-{
- return EC_IMAGE_RO;
-}
+/* Variables to emulate the protection */
+bool ro_protected, all_protected;
-void system_set_image_copy(enum ec_image copy)
+static int cros_flash_emul_init(const struct device *dev)
{
+ struct flash_emul_data *data = DRV_DATA(dev);
+
+ data->flash_dev = DEVICE_DT_GET(FLASH_DEV);
+ if (!device_is_ready(data->flash_dev)) {
+ LOG_ERR("%s device not ready", data->flash_dev->name);
+ return -ENODEV;
+ }
+
+ return EC_SUCCESS;
}
-static int cros_flash_emul_init(const struct device *dev)
+static int flash_check_writable_range(int offset, int size)
{
- return 0;
+ /* Check out of range */
+ if (offset + size > CONFIG_FLASH_SIZE_BYTES) {
+ return EC_ERROR_INVAL;
+ }
+
+ /* Check RO protected and within the RO range */
+ if (ro_protected &&
+ MAX(CONFIG_WP_STORAGE_OFF, offset) <
+ MIN(CONFIG_WP_STORAGE_OFF + CONFIG_WP_STORAGE_SIZE,
+ offset + size)) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ return EC_SUCCESS;
}
static int cros_flash_emul_write(const struct device *dev, int offset, int size,
const char *src_data)
{
- __ASSERT(false, "Not implemented");
- return -EINVAL;
+ int ret = 0;
+ struct flash_emul_data *data = DRV_DATA(dev);
+
+ /* Check protection */
+ if (all_protected) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ if (flash_check_writable_range(offset, size)) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ /* Check invalid data pointer? */
+ if (src_data == 0) {
+ return -EINVAL;
+ }
+
+ /* Lock physical flash operations */
+ crec_flash_lock_mapped_storage(1);
+
+ ret = flash_write(data->flash_dev, offset, src_data, size);
+
+ /* Unlock physical flash operations */
+ crec_flash_lock_mapped_storage(0);
+
+ return ret;
}
static int cros_flash_emul_erase(const struct device *dev, int offset, int size)
{
- __ASSERT(false, "Not implemented");
- return -EINVAL;
+ int ret = 0;
+ struct flash_emul_data *data = DRV_DATA(dev);
+
+ /* Check protection */
+ if (all_protected) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ if (flash_check_writable_range(offset, size)) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ /* Address must be aligned to erase size */
+ if ((offset % CONFIG_FLASH_ERASE_SIZE) != 0) {
+ return -EINVAL;
+ }
+
+ /* Erase size must be a non-zero multiple of sectors */
+ if ((size == 0) || (size % CONFIG_FLASH_ERASE_SIZE) != 0) {
+ return -EINVAL;
+ }
+
+ /* Lock physical flash operations */
+ crec_flash_lock_mapped_storage(1);
+
+ ret = flash_erase(data->flash_dev, offset, size);
+
+ /* Unlock physical flash operations */
+ crec_flash_lock_mapped_storage(0);
+
+ return ret;
}
static int cros_flash_emul_get_protect(const struct device *dev, int bank)
{
- __ASSERT(false, "Not implemented");
- return -EINVAL;
+ if (all_protected) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+ if (ro_protected && bank >= WP_BANK_OFFSET &&
+ bank < WP_BANK_OFFSET + WP_BANK_COUNT) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ return EC_SUCCESS;
}
static uint32_t cros_flash_emul_get_protect_flags(const struct device *dev)
{
- return EC_FLASH_PROTECT_ERROR_UNKNOWN;
+ uint32_t flags = 0;
+
+ if (ro_protected) {
+ flags |= EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW;
+ }
+ if (all_protected) {
+ flags |= EC_FLASH_PROTECT_ALL_NOW;
+ }
+ return flags;
}
static int cros_flash_emul_protect_at_boot(const struct device *dev,
uint32_t new_flags)
{
- __ASSERT(false, "Not implemented");
- return -EINVAL;
+ if ((new_flags & (EC_FLASH_PROTECT_RO_AT_BOOT |
+ EC_FLASH_PROTECT_ALL_AT_BOOT)) == 0) {
+ /* Clear protection if allowed */
+ if (crec_flash_get_protect() & EC_FLASH_PROTECT_GPIO_ASSERTED) {
+ return EC_ERROR_ACCESS_DENIED;
+ }
+
+ ro_protected = all_protected = false;
+ return EC_SUCCESS;
+ }
+
+ ro_protected = true;
+
+ if (new_flags & EC_FLASH_PROTECT_ALL_AT_BOOT) {
+ all_protected = true;
+ }
+
+ return EC_SUCCESS;
}
static int cros_flash_emul_protect_now(const struct device *dev, int all)
{
- __ASSERT(false, "Not implemented");
- return -EINVAL;
+ /* Emulate ALL_NOW only */
+ if (all) {
+ all_protected = true;
+ }
+
+ return EC_SUCCESS;
+}
+
+void cros_flash_emul_protect_reset(void)
+{
+ ro_protected = all_protected = false;
}
static int cros_flash_emul_get_jedec_id(const struct device *dev,
@@ -98,7 +208,6 @@ static int cros_flash_emul_get_status(const struct device *dev, uint8_t *sr1,
return -EINVAL;
}
-
static const struct cros_flash_driver_api emul_cros_flash_driver_api = {
.init = cros_flash_emul_init,
.physical_write = cros_flash_emul_write,
@@ -118,17 +227,14 @@ static int flash_emul_init(const struct device *dev)
return 0;
}
-#define FLASH_EMUL(n) \
- static struct flash_emul_data flash_emul_data_##n = { \
- }; \
- \
- static const struct flash_emul_cfg flash_emul_cfg_##n = { \
- .dev_label = DT_INST_LABEL(n), \
- .data = &flash_emul_data_##n, \
- }; \
- DEVICE_DT_INST_DEFINE(n, flash_emul_init, NULL, \
- &flash_emul_data_##n, &flash_emul_cfg_##n, \
- PRE_KERNEL_1, \
- CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
+#define FLASH_EMUL(n) \
+ static struct flash_emul_data flash_emul_data_##n = {}; \
+ \
+ static const struct flash_emul_cfg flash_emul_cfg_##n = { \
+ .data = &flash_emul_data_##n, \
+ }; \
+ DEVICE_DT_INST_DEFINE(n, flash_emul_init, NULL, &flash_emul_data_##n, \
+ &flash_emul_cfg_##n, PRE_KERNEL_1, \
+ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&emul_cros_flash_driver_api)
DT_INST_FOREACH_STATUS_OKAY(FLASH_EMUL);