[Skiboot] [RFC PATCH 1/2] libflash/blocklevel: Optionally always return opal-api return codes
Cyril Bur
cyril.bur at au1.ibm.com
Wed Jan 25 18:56:52 AEDT 2017
With the introduction of the blocklevel abstraction layer some of the
return code passing got neglected. This isn't a very big deal for
skiboot/external tools however this can be a problem in skiboot proper.
Some of the opal-api calls could pass back values from blocklevel
directly along the api in which case it is quite important that the
values are valid and make some sense.
Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
---
libflash/Makefile.inc | 4 ++-
libflash/blocklevel-errors.c | 67 ++++++++++++++++++++++++++++++++++++++++++++
libflash/blocklevel-errors.h | 30 ++++++++++++++++++++
libflash/blocklevel.c | 59 +++++++++++++++++++++-----------------
libflash/blocklevel.h | 3 ++
5 files changed, 137 insertions(+), 26 deletions(-)
create mode 100644 libflash/blocklevel-errors.c
create mode 100644 libflash/blocklevel-errors.h
diff --git a/libflash/Makefile.inc b/libflash/Makefile.inc
index 4db02a1f..184524f9 100644
--- a/libflash/Makefile.inc
+++ b/libflash/Makefile.inc
@@ -1,4 +1,6 @@
-LIBFLASH_SRCS = libflash.c libffs.c ecc.c blocklevel.c
+LIBFLASH_SRCS = libflash.c libffs.c ecc.c blocklevel.c \
+ blocklevel-errors.c
+
LIBFLASH_OBJS = $(LIBFLASH_SRCS:%.c=%.o)
SUBDIRS += libflash
diff --git a/libflash/blocklevel-errors.c b/libflash/blocklevel-errors.c
new file mode 100644
index 00000000..16160d95
--- /dev/null
+++ b/libflash/blocklevel-errors.c
@@ -0,0 +1,67 @@
+/* Copyright 2017 IBM Corp.
+ *
+ * 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.
+ */
+
+#ifndef __SKIBOOT__
+#error "It doesn't make sense to use this outside skiboot proper"
+#endif
+
+#include <opal-api.h>
+
+#include <libflash/blocklevel.h>
+#include <libflash/blocklevel-errors.h>
+#include <libflash/errors.h>
+
+int check_rc(struct blocklevel_device *bl, int rc)
+{
+ if (!(bl->flags & OPAL_RETURN_CODE_ONLY) || rc < 1)
+ return rc;
+
+ switch (rc) {
+ case FLASH_ERR_MALLOC_FAILED:
+ return OPAL_NO_MEM;
+
+ case FLASH_ERR_CHIP_UNKNOWN:
+ return OPAL_HARDWARE;
+
+ case FLASH_ERR_PARM_ERROR:
+ return OPAL_PARAMETER;
+
+ case FLASH_ERR_ERASE_BOUNDARY:
+ return OPAL_UNSUPPORTED; /* or just OPAL_PARAMETER? */
+
+ case FLASH_ERR_WREN_TIMEOUT:
+ case FLASH_ERR_WIP_TIMEOUT:
+ case FLASH_ERR_VERIFY_FAILURE:
+ return OPAL_INTERNAL_ERROR;
+
+ case FLASH_ERR_4B_NOT_SUPPORTED:
+ return OPAL_UNSUPPORTED;
+
+ case FLASH_ERR_CTRL_CONFIG_MISMATCH:
+ return OPAL_INTERNAL_ERROR;
+
+ case FLASH_ERR_CHIP_ER_NOT_SUPPORTED:
+ case FLASH_ERR_CTRL_CMD_UNSUPPORTED:
+ return OPAL_UNSUPPORTED;
+
+ case FLASH_ERR_CTRL_TIMEOUT:
+ case FLASH_ERR_ECC_INVALID:
+ case FLASH_ERR_BAD_READ:
+ return OPAL_INTERNAL_ERROR;
+ }
+
+ return rc;
+}
diff --git a/libflash/blocklevel-errors.h b/libflash/blocklevel-errors.h
new file mode 100644
index 00000000..e01f7ce3
--- /dev/null
+++ b/libflash/blocklevel-errors.h
@@ -0,0 +1,30 @@
+/* Copyright 2017 IBM Corp.
+ *
+ * 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.
+ */
+
+#ifndef __LIBFLASH_BLOCKLEVEL_ERRORS_H
+#define __LIBFLASH_BLOCKLEVEL_ERRORS_H
+
+#include <libflash/blocklevel.h>
+
+#ifdef __SKIBOOT__
+int check_rc(struct blocklevel_device *bl, int rc);
+#else
+static inline int check_rc(struct blocklevel_device *bl __attribute__((unused)), int rc)
+{
+ return rc;
+}
+#endif
+#endif /* __LIBFLASH_BLOCKLEVEL_ERRORS_H */
diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c
index 79ff00f4..c0057fa8 100644
--- a/libflash/blocklevel.c
+++ b/libflash/blocklevel.c
@@ -23,6 +23,7 @@
#include <inttypes.h>
#include <libflash/errors.h>
+#include <libflash/blocklevel-errors.h>
#include "blocklevel.h"
#include "ecc.h"
@@ -84,18 +85,18 @@ int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, u
if (!bl || !bl->read || !buf) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
rc = reacquire(bl);
if (rc)
- return rc;
+ return check_rc(bl, rc);
rc = bl->read(bl, pos, buf, len);
release(bl);
- return rc;
+ return check_rc(bl, rc);
}
int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
@@ -106,11 +107,11 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6
if (!bl || !buf) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
if (!ecc_protected(bl, pos, len))
- return blocklevel_raw_read(bl, pos, buf, len);
+ return blocklevel_raw_read(bl, pos, buf, len); /* This checks its return code */
buffer = malloc(ecc_len);
if (!buffer) {
@@ -130,7 +131,7 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6
out:
free(buffer);
- return rc;
+ return check_rc(bl, rc);
}
int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos,
@@ -140,18 +141,18 @@ int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos,
if (!bl || !bl->write || !buf) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
rc = reacquire(bl);
if (rc)
- return rc;
+ return check_rc(bl, rc);
rc = bl->write(bl, pos, buf, len);
release(bl);
- return rc;
+ return check_rc(bl, rc);
}
int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf,
@@ -163,11 +164,11 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf
if (!bl || !buf) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
if (!ecc_protected(bl, pos, len))
- return blocklevel_raw_write(bl, pos, buf, len);
+ return blocklevel_raw_write(bl, pos, buf, len); /* This checks its return code */
buffer = malloc(ecc_len);
if (!buffer) {
@@ -186,7 +187,7 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf
out:
free(buffer);
- return rc;
+ return check_rc(bl, rc);
}
int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
@@ -194,25 +195,25 @@ int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
int rc;
if (!bl || !bl->erase) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
/* Programmer may be making a horrible mistake without knowing it */
if (len & bl->erase_mask) {
fprintf(stderr, "blocklevel_erase: len (0x%"PRIx64") is not erase block (0x%08x) aligned\n",
len, bl->erase_mask + 1);
- return FLASH_ERR_ERASE_BOUNDARY;
+ return check_rc(bl, FLASH_ERR_ERASE_BOUNDARY);
}
rc = reacquire(bl);
if (rc)
- return rc;
+ return check_rc(bl, rc);
rc = bl->erase(bl, pos, len);
release(bl);
- return rc;
+ return check_rc(bl, rc);
}
int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,
@@ -222,12 +223,12 @@ int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_
if (!bl || !bl->get_info) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
rc = reacquire(bl);
if (rc)
- return rc;
+ return check_rc(bl, rc);
rc = bl->get_info(bl, name, total_size, erase_granule);
@@ -238,7 +239,7 @@ int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_
release(bl);
- return rc;
+ return check_rc(bl, rc);
}
/*
@@ -280,13 +281,13 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi
if (!write_buf || !bl) {
errno = EINVAL;
- return FLASH_ERR_PARM_ERROR;
+ return check_rc(bl, FLASH_ERR_PARM_ERROR);
}
if (!(bl->flags & WRITE_NEED_ERASE))
- return blocklevel_write(bl, pos, buf, len);
+ return blocklevel_write(bl, pos, buf, len); /* This checks its return code */
- rc = blocklevel_get_info(bl, NULL, NULL, &erase_size);
+ rc = blocklevel_get_info(bl, NULL, NULL, &erase_size); /* This checks its return code */
if (rc)
return rc;
@@ -296,13 +297,13 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi
write_buf_start = malloc(len);
if (!write_buf_start) {
errno = ENOMEM;
- return FLASH_ERR_MALLOC_FAILED;
+ return check_rc(bl, FLASH_ERR_MALLOC_FAILED);
}
if (memcpy_to_ecc(write_buf_start, buf, ecc_buffer_size_minus_ecc(len))) {
free(write_buf_start);
errno = EBADF;
- return FLASH_ERR_ECC_INVALID;
+ return check_rc(bl, FLASH_ERR_ECC_INVALID);
}
write_buf = write_buf_start;
}
@@ -352,7 +353,7 @@ out:
out_free:
free(write_buf_start);
free(erase_buf);
- return rc;
+ return check_rc(bl, rc);
}
static bool insert_bl_prot_range(struct blocklevel_range *ranges, struct bl_prot_range range)
@@ -459,3 +460,11 @@ int blocklevel_ecc_protect(struct blocklevel_device *bl, uint32_t start, uint32_
return -1;
return !insert_bl_prot_range(&bl->ecc_prot, range);
}
+
+void blocklevel_force_opal_codes(struct blocklevel_device *bl)
+{
+ if (!bl)
+ return;
+
+ bl->flags |= OPAL_RETURN_CODE_ONLY;
+}
diff --git a/libflash/blocklevel.h b/libflash/blocklevel.h
index 09f0096a..bf6def7a 100644
--- a/libflash/blocklevel.h
+++ b/libflash/blocklevel.h
@@ -32,6 +32,7 @@ struct blocklevel_range {
enum blocklevel_flags {
WRITE_NEED_ERASE = 1,
+ OPAL_RETURN_CODE_ONLY = 2,
};
/*
@@ -78,4 +79,6 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi
/* Implemented in software at this level */
int blocklevel_ecc_protect(struct blocklevel_device *bl, uint32_t start, uint32_t len);
+void blocklevel_force_opal_codes(struct blocklevel_device *bl);
+
#endif /* __LIBFLASH_BLOCKLEVEL_H */
--
2.11.0
More information about the Skiboot
mailing list