-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Early TAs #1733
Early TAs #1733
Conversation
core/arch/arm/kernel/early_ta.c
Outdated
strm->zfree = zfree; | ||
st = inflateInit(strm); | ||
if (st != Z_OK) { | ||
DMSG("Early TA decompression initialization error (%d)", st); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EMSG?
if (ta->uncompressed_size) | ||
*size = ta->uncompressed_size; | ||
else | ||
*size = ta->size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: blank line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*size
is set twice. Looks like an error: I guess *size = h->early_ta->size;
below should be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops! Will fix. I introduced this bug when I addressed @igoropaniuk's comment.
return TEE_ERROR_BAD_PARAMETERS; | ||
if (data) | ||
memcpy(data, src, len); | ||
h->offs += len; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: blank line
{ | ||
z_stream *strm = &h->strm; | ||
size_t total = 0; | ||
uint8_t *tmpbuf = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unneeded initialization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thoughts exactly, but GCC 6.2.1 doesn't like it:
$ make PLATFORM=hikey CFG_EARLY_TA=y out/arm-plat-hikey/core/arch/arm/kernel/early_ta.o
CHK out/arm-plat-hikey/conf.mk
CHK out/arm-plat-hikey/include/generated/conf.h
CC out/arm-plat-hikey/core/arch/arm/kernel/early_ta.o
core/arch/arm/kernel/early_ta.c: In function ‘early_ta_read’:
core/arch/arm/kernel/early_ta.c:198:3: error: ‘tmpbuf’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
free(tmpbuf);
^
core/arch/arm/kernel/early_ta.c:148:11: note: ‘tmpbuf’ was declared here
uint8_t *tmpbuf;
^
cc1: all warnings being treated as errors
mk/compile.mk:146: recipe for target 'out/arm-plat-hikey/core/arch/arm/kernel/early_ta.o' failed
make: *** [out/arm-plat-hikey/core/arch/arm/kernel/early_ta.o] Error 1
.get_size = early_ta_get_size, | ||
.read = early_ta_read, | ||
.close = early_ta_close, | ||
.priority = 5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add comment about priority field, what does it stand for
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment added in core/arch/arm/kernel/elf_load.h
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest to define those magic priority values in user_ta.h (i.e EARLY_TA_STORE_PRIORITY
and REE_TA_STORE_PRIORITY
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think user_ta.h
should not need to know about the various TA stores, so I'd rather avoid that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
scripts/ta_bin_to_c.py
Outdated
return parser.parse_args() | ||
|
||
def main(): | ||
import array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible holy war, but https://stackoverflow.com/questions/1024049/is-it-pythonic-to-import-inside-functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change. I also have a slight preference for imports at the top, probably because I'm essentially developing in C ;)
@@ -94,6 +94,12 @@ libdir = core/lib/libfdt | |||
include mk/lib.mk | |||
endif | |||
|
|||
ifeq ($(CFG_ZLIB),y) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess when CFG_ZLIB
isn't set early_ta.c
won't compile?
Is it possible to use early TA feature without compression support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Making compression support optional is doable of course, but it would make the code a bit harder to read (several #ifdef's in early_ta.c
).
core/arch/arm/kernel/early_ta.c
Outdated
DMSG("Early TA decompression initialization error (%d)", st); | ||
return false; | ||
} | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: blank line
f = open(args.out, 'w') | ||
f.write('/* Generated from ' + args.ta + ' by ' + | ||
os.path.basename(__file__) + ' */\n\n') | ||
f.write('#include <compiler.h>\n'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not to move creation of stub to separate function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would mean moving almost everything from main()
to generate_file()
, no? So what would be the benefit?
core/arch/arm/kernel/early_ta.c
Outdated
#include <kernel/early_ta.h> | ||
#include <kernel/linker.h> | ||
#include <kernel/user_ta.h> | ||
#include <zlib.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: include order
core/arch/arm/kernel/early_ta.c
Outdated
out: | ||
if (!data) | ||
free(tmpbuf); | ||
return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: blank line
55a838e
to
9ec0c57
Compare
if (ta->uncompressed_size) | ||
*size = ta->uncompressed_size; | ||
else | ||
*size = ta->size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*size
is set twice. Looks like an error: I guess *size = h->early_ta->size;
below should be removed.
core/arch/arm/kernel/early_ta.c
Outdated
total += out; | ||
FMSG("%zu bytes", out); | ||
if (!data) { | ||
strm->next_out = tmpbuf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: strm->next_out = tmpbuf;
seems useless: already set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, that's for the case we're asked to read more than 1K of uncompressed data and throw them away (data == NULL). We read 1K chunks at a time. By resetting the pointer on each loop I try to read as much as possible each time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean we need to reset the output buffer point to the temp buff start address ?
Maybe this deserves a small comment. (maybe not :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. I will add a comment.
core/arch/arm/kernel/early_ta.c
Outdated
* stream nor the end of the output buffer were met | ||
* - Z_BUF_ERROR when there is still input to process but the output | ||
* buffer is full | ||
* - Z_STREAM_END when the end of the intput stream was reached |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate a bit these comments, stating which return values relate excepted successful content read? (the loop implementation is not that obvious)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose while ((st == Z_OK) && (total != len))
is obvious, right? So it's only the Z_BUF_ERROR
case, not being an error here, that deserves some clarification?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading again the current comment, I found it clear. Maybe move Z_STREAM_END
description next to Z_OK
. It would look less like an error case (as right after Z_BUF_ERROR
);
Minor: add a terminal dots to each bullet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
core/arch/arm/kernel/early_ta.c
Outdated
strm->avail_out = MIN(len - total, 1024U); | ||
} | ||
} while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len)); | ||
if (st != Z_OK && st != Z_STREAM_END && st != Z_BUF_ERROR) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect here (once read loop is done) that st == Z_BUF_ERROR
is an error case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'll remove this check.
core/arch/arm/kernel/early_ta.c
Outdated
} | ||
ret = TEE_SUCCESS; | ||
out: | ||
if (!data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: can call free(tmpbuf)
straight since pointer is NULL
initialized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
mk/config.mk
Outdated
@@ -176,6 +176,26 @@ CFG_WITH_USER_TA ?= y | |||
# case you implement your own TA store | |||
CFG_REE_FS_TA ?= y | |||
|
|||
# Support for loading user TAs from a special section in the TEE binary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: add terminal dot.
mk/config.mk
Outdated
@@ -176,6 +176,26 @@ CFG_WITH_USER_TA ?= y | |||
# case you implement your own TA store | |||
CFG_REE_FS_TA ?= y | |||
|
|||
# Support for loading user TAs from a special section in the TEE binary | |||
# Such TAs are available even before tee-supplicant is available (hence their | |||
# name), but note that many services exported to TAs may need tee-supplicant, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think EARLY_TA should be rename BUILTIN_TA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, BUILTIN_TA better describes what they really are. If no one objects I'll rename everything once we're done with the review. Otherwise it will bee too complex to follow the changes.
mk/config.mk
Outdated
# so early use is limited to a subset of the TEE Internal Core API (crypto...) | ||
# To use this feature, set EARLY_TA to the paths to one or more TA ELF file(s) | ||
# For example: | ||
# EARLY_TA=path/to/8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From this description it is not clear whether one should define several EARLY_TA values (sic) each defining the full path of the TA elf file or if EARLY_TA is expected a unique directory path where one can store several TA ELF files to be embedded in the core binary.
As EARLY_TA
is a configuration directive, I would suggest to prefix it CFG_EARLY_TA_PATH
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update the comment. What's expected is one or more paths to TA files separated with spaces, such as:
EARLY_TA="../optee_test/out/ta/crypt/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.stripped.elf ../optee_test/out/ta/aes_perf/e626662e-c0e2-485c-b8c8-09fbce6edf3d.stripped.elf"
Regarding the lack of CFG_
prefix: you're mostly right but there's a trick (that I should document): all CFG_
variables are written to $(out-dir)/conf.mk
and any change to the values in this file causes a re-compilation of everything. So, consider the build steps I have given as an example:
$ make CFG_EARLY_TA=y # (1)
<build some TAs> # (2)
$ make ... EARLY_TA=/some/path # (3)
You can't give CFG_EARLY_TA_PATH
during step (1) since we assume the TAs have not been built yet (they need optee_os to be built first so that dev_kit is available). So you can't have CFG_EARLY_TA_PATH
set to the same value in steps (1) and (3) thus causing a full rebuilt of optee_os at step (3).
I propose to rename EARLY_TA
and use BUILTIN_TA_PATHS
instead (will do it at the same time I replace "early" with "builtin").
|
||
struct early_ta { | ||
TEE_UUID uuid; | ||
uint32_t flags; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flags seems useless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leftover from a previous implementation... will remove, thanks
core/arch/arm/kernel/elf_load.h
Outdated
* For debug purposes only. | ||
*/ | ||
const char *description; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: remove empty line (for consistency) ?
core/arch/arm/kernel/elf_load.h
Outdated
@@ -62,6 +69,13 @@ struct user_ta_store_ops { | |||
* Close a TA handle. Do nothing if @h == NULL. | |||
*/ | |||
void (*close)(struct user_ta_store_handle *h); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: remove empty line (for consistency) ?
core/arch/arm/kernel/early_ta.c
Outdated
total += out; | ||
FMSG("%zu bytes", out); | ||
if (!data) { | ||
strm->next_out = tmpbuf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean we need to reset the output buffer point to the temp buff start address ?
Maybe this deserves a small comment. (maybe not :)
core/arch/arm/kernel/kern.ld.S
Outdated
@@ -329,6 +336,11 @@ SECTIONS | |||
KEEP(*(.rodata.dtdrv)) | |||
__rodata_dtdrv_end = .; | |||
#endif | |||
#ifdef CFG_EARLY_TA | |||
__rodata_early_ta_start = .; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
. = ALIGN(8);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally remove the 8 byte alignment.
core/arch/arm/kernel/user_ta.c
Outdated
ops->priority); | ||
|
||
SLIST_FOREACH(e, &uta_store_list, link) { | ||
if (e->priority > ops->priority) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add assert(e->priority != ops->priority);
before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I would allow equal priorities, but it may be a bad idea (invocation order would depend on registration order which may not be well controlled...). I will add the assert.
core/arch/arm/plat-sunxi/kern.ld.S
Outdated
@@ -129,6 +129,11 @@ SECTIONS | |||
|
|||
.rodata : ALIGN(4) { | |||
__rodata_start = .; | |||
#ifdef CFG_EARLY_TA | |||
__rodata_early_ta_start = .; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
. = ALIGN(8);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
core/arch/arm/kernel/early_ta.c
Outdated
* stream nor the end of the output buffer were met | ||
* - Z_BUF_ERROR when there is still input to process but the output | ||
* buffer is full | ||
* - Z_STREAM_END when the end of the intput stream was reached |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading again the current comment, I found it clear. Maybe move Z_STREAM_END
description next to Z_OK
. It would look less like an error case (as right after Z_BUF_ERROR
);
Minor: add a terminal dots to each bullet.
core/arch/arm/kernel/early_ta.c
Outdated
#define for_each_early_ta(_ta) \ | ||
for (_ta = &__rodata_early_ta_start; ta < &__rodata_early_ta_end; \ | ||
_ta = (const struct early_ta *) \ | ||
ROUNDUP((vaddr_t)ta + sizeof(*ta) + ta->size, 8)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few ta
to replace with _ta
in the macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good catch
core/arch/arm/kernel/early_ta.c
Outdated
return TEE_ERROR_OUT_OF_MEMORY; | ||
|
||
if (ta->uncompressed_size) { | ||
/* TA is compressed */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: I think this comment is useless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, it is redundant with /* 0: not compressed */
in early_ta.h
. Will remove it.
.get_size = early_ta_get_size, | ||
.read = early_ta_read, | ||
.close = early_ta_close, | ||
.priority = 5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest to define those magic priority values in user_ta.h (i.e EARLY_TA_STORE_PRIORITY
and REE_TA_STORE_PRIORITY
).
core/arch/arm/kernel/early_ta.c
Outdated
" (compressed, uncompressed %u)", | ||
ta->uncompressed_size); | ||
DMSG("Early TA %pUl size %u%s", (void *)&ta->uuid, ta->size, | ||
msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must reset msg[0] = '\0'
in the loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
core/arch/arm/kernel/elf_load.h
Outdated
* Higher priority instances are tried first when a TA is looked up. | ||
*/ | ||
SLIST_ENTRY(user_ta_store_ops) link; | ||
int priority; /* Lower value means higher priority */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: comment above the field (rather than appended in the same line) ?
@@ -324,11 +324,13 @@ static void ta_close(struct user_ta_store_handle *h) | |||
free(h); | |||
} | |||
|
|||
static const struct user_ta_store_ops ops = { | |||
static struct user_ta_store_ops ops = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really need to remove the const
qualifier ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, because link
is modified when the structure is put in the TA store list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right. thanks.
core/arch/arm/kernel/user_ta.c
Outdated
SLIST_FOREACH(e, &uta_store_list, link) { | ||
/* | ||
* Do not allow equal priorities to avoid any dependency on | ||
* registration order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: terminal dot.
mk/config.mk
Outdated
# $ make ... CFG_EARLY_TA=y # Enable the feature to avoid later recompilation | ||
# <build some TAs> | ||
# $ make ... EARLY_TA_PATHS=<paths> # Embbed the TA(s) (will re-link OP-TEE) | ||
ifneq ($(EARLY_TA),) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/EARLY_TA/EARLY_TA_PATHS/
core/sub.mk
Outdated
cleanfiles += $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c | ||
cflags-remove-early-ta-$1-y := -pedantic | ||
endef | ||
$(foreach f, $(EARLY_TA), $(eval $(call process_early_ta,$(f)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/EARLY_TA
/EARLY_TA_PATHS
/
Could you check that this works ok even if EARLY_TA_PATHS
is empty or even not defined ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does work
core/arch/arm/kernel/user_ta.c
Outdated
res = ta_load(uuid, store, &s->ctx); | ||
if (res == TEE_SUCCESS) { | ||
s->ctx->ops = &user_ta_ops; | ||
return res; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, I wonder if we should try other stores only if ta_load()
returns TEE_ERROR_ITEM_NOT_FOUND
.
I mean that if the target uuid was found in the early TAs, the TA binary is expected valid. For example, if core lacks of heap was loading an early TA, it should not try the load the TA from the REE.
In the same scope, how should core behave of an early TA shows formatting issues. I think it should panic if in debug mode, and simply refuse to load REE TA instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not trying the next store in case of error other than TEE_ERROR_ITEM_NOT_FOUND
is also a valid option I think, but why would it be better? I'd rather keep the current code for the moment. If we later find out that some use cases require a different behavior, we'll change the logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this code if an early TA has formatting issues and there isn't a backup version in REE it would return TEE_ERROR_ITEM_NOT_FOUND
instead of the actual error code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, how about this?
SLIST_FOREACH(store, &uta_store_list, link) {
DMSG("Lookup user TA %pUl (%s)", (void *)uuid,
store->description);
res = ta_load(uuid, store, &s->ctx);
if (res == TEE_ERROR_ITEM_NOT_FOUND)
continue;
if (res == TEE_SUCCESS)
s->ctx->ops = &user_ta_ops;
else
DMSG("res=0x%x", res);
return res;
}
return TEE_ERROR_ITEM_NOT_FOUND;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
.get_size = early_ta_get_size, | ||
.read = early_ta_read, | ||
.close = early_ta_close, | ||
.priority = 5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
I think this change is pretty nice as it is. See my last comment regarding load error cases. I have not reviewed the zlib implementation :) and will only ack the python scripting. |
Update: fixed issue that |
$(if $(strip $(filter-out $(link-objs), $(old-link-objs)) | ||
$(filter-out $(old-link-objs), $(link-objs))), FORCE_LINK := FORCE) | ||
endef | ||
$(eval $(call check-link-objs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fear this will not force relink if one updates an already existing TA ELF file.
Maybe it could be more simple to simple force relink if EARLY_TA_PATH is defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a TA is modified, the C file will become outdated and will be generated again. It's not something that is handled by this. This only takes care of the situation when no files are modified (because they are already all present and up-to-date from a previous build), but tee.elf should still be re-linked to add/remove files.
core/arch/arm/kernel/sub.mk
Outdated
@@ -1,6 +1,8 @@ | |||
ifeq ($(CFG_WITH_USER_TA),y) | |||
srcs-y += user_ta.c | |||
srcs-$(CFG_REE_FS_TA) += ree_fs_ta.c | |||
srcs-$(CFG_EARLY_TA) += early_ta.c | |||
cflags-early_ta.c-y += -Wno-discarded-qualifiers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compile error with gcc version 4.9.2 20140904:
cc1: error: unrecognized command line option "-Wno-discarded-qualifiers" [-Werror]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
{ | ||
int st; | ||
|
||
strm->next_in = ta->ta; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core/arch/arm/kernel/early_ta.c:77:16: error: assignment discards 'const' qualifier from pointer target type [-Werror]
ZLIB_CONST defined in ./lib/libzlib/include/zconf.h, but not defined in ./core/lib/zlib/zconf.h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the hint, I'll fix this whole const
handling issue by defining ZLIB_CONST
and removing -Wno-discarded-qualifiers
.
mk/config.mk
Outdated
# EARLY_TA_PATHS="path/to/8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf \ | ||
# path/to/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.stripped.elf" | ||
# Typical build steps: | ||
# $ make ... CFG_EARLY_TA=y # Enable the feature to avoid later recompilation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As CFG_EARLY_TA=y, EARLY_TA_PATHS=test_ta_uuid.
When test_ta and optee_os are both modified, need to make twice optee_os.
May it add "make headers_install"? Build headers for TA first, then build TA, finally build optee_os.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please note that, if you build optee_os with CFG_EARLY_TA=y
first, and EARLY_TA_PATHS
not set as explained in the comment, then optee_os will not be built twice. Only the link step will occur again when you run make EARLY_TA_PATHS=test_ta_uuid.elf
.
That being said, I will see if I can do what you propose (add make headers_install
). Shouldn't be that hard.
All review comments addressed (or replied to), I think. We have lots of review fix-ups so I will probably squash the commits together properly before asking for a last round of reviews. When doing so, should I rename "early" to "built-in" as suggested previously (that is, |
uint32_t size; | ||
uint32_t uncompressed_size; /* 0: not compressed */ | ||
const uint8_t ta[]; /* @size bytes */ | ||
} __aligned(8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this alignment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It helps iterate on the early_ta
structs in the .rodata
section. Without this, the compiler tends to align the structure on either 4 or 8 bytes and it depends on the arch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the problem with different alignment depending on the arch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I used __alignof__(struct early_ta)
(instead of hard-coding 8) for rounding up the size of structs when iterating (here). It was OK on QEMU but I was 4 bytes off on D02 (64-bits). So I forced 8-byte alignement as an easy fix ;)
I'll take a closer look and see if I can get rid of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed by applying __aligned(__alignof__(struct early_ta))
to each variable of this type (see the Python script). Results in all variables being 4-bytes aligned on 32-bit as well as 64-bit platforms with no unwanted padding. I noticed that applying the same align
attribute to the type or the variable is not equivalent, but could not figure out if it's expected or not...
core/arch/arm/kernel/user_ta.c
Outdated
res = ta_load(uuid, store, &s->ctx); | ||
if (res == TEE_SUCCESS) { | ||
s->ctx->ops = &user_ta_ops; | ||
return res; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this code if an early TA has formatting issues and there isn't a backup version in REE it would return TEE_ERROR_ITEM_NOT_FOUND
instead of the actual error code.
Apply changes proposed in review comment [1] (handle load errors differently). Link: [1] OP-TEE#1733 (comment) Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comment. looks good to me.
@@ -129,6 +129,12 @@ SECTIONS | |||
|
|||
.rodata : ALIGN(4) { | |||
__rodata_start = .; | |||
#ifdef CFG_EARLY_TA | |||
. = ALIGN(8); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alignment to remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
core/arch/arm/kernel/kern.ld.S
Outdated
@@ -329,6 +336,11 @@ SECTIONS | |||
KEEP(*(.rodata.dtdrv)) | |||
__rodata_dtdrv_end = .; | |||
#endif | |||
#ifdef CFG_EARLY_TA | |||
__rodata_early_ta_start = .; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally remove the 8 byte alignment.
# Such TAs are available even before tee-supplicant is available (hence their | ||
# name), but note that many services exported to TAs may need tee-supplicant, | ||
# so early use is limited to a subset of the TEE Internal Core API (crypto...) | ||
# To use this feature, set EARLY_TA_PATHS to the paths to one or more TA ELF |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As EARLY_TA_PATHS is a configuration directive that affects the core embedded content, i would rather have it prefixed CFG_
. Your feeling ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No CFG_
to avoid re-building: #1733 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I see the point (I had forgotten that). However it looks rather like a workaround on the config to suite the current build process.
I wonder if we could split the optee_os build in 2:
- build core only (libs + core): i.e
make core
- build user land only (libs + devkit): i.e
make ta_devkit
In most cases (no early TA), one could run make all
to get everything in place.
For early TAs support: first build the user libs, then build the (early) TAs, then build core with the early TAs. This would help generating a conf.mk that would reflect the real configuration used to build the core binary. This is change is related to that some platform could allow the TAs to build their own 'static' libraries independently from the core configuration: enabling some debug, profiling,traces for some TAs but not for all. But maybe that should be discussed later on...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have already added make ta_dev_kit
, after @airbak's suggestion above. So indeed, we could very well use CFG_EARLY_TA_PATHS
as you suggest and still avoid re-compilation.
Let me give it a try and update ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@etienne-lms ultimately I think CFG_ is not very convenient. During testing I have changed several times the list of applications (adding one or two, changing them), and with CFG_ the tee.bin is fully recompiled each time and it's a bit painful.
So I'm not changing the prefix. We can change later depending on the use cases.
This P-R went to a good point (at least to my appraisal). You would like some review/ack tags or do we change early_ta into builtin_ta or whatever before tagging? |
@etienne-lms I have cleaned up and reordered the series, let's gather the review tags now.
19e34cf Remove leading spaces and dots in DMSG() messages |
core/arch/arm/kernel/user_ta.c
Outdated
@@ -625,16 +625,19 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid, | |||
struct tee_ta_session *s) | |||
{ | |||
const struct user_ta_store_ops *store; | |||
TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; | |||
TEE_Result res; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though these changes where to go into 6ae578d "Add support for several user TA stores"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My mistake, will fix.
core/arch/arm/kernel/kern.ld.S
Outdated
@@ -329,6 +335,11 @@ SECTIONS | |||
KEEP(*(.rodata.dtdrv)) | |||
__rodata_dtdrv_end = .; | |||
#endif | |||
#ifdef CFG_EARLY_TA | |||
__rodata_early_ta_start = .; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is __rodata_dtdrv_end
guaranteed to end on a well aligned address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Strictly speaking we should have . = ALIGN(__alignof__(struct early_ta))
but that can't be understood by the linker. Our options are:
- Hard-code 4, which I expect to be the value of
__alignof__(struct early_ta)
for pretty much all platforms currently. - Use 8 for greater safety (?)
- Add a definition to asm-defines.c.
I am tempted to do (3) although it may look weird to use this "asm" file for that purpose. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're usually doing 2. in the link script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
core/sub.mk
Outdated
recipe-early-ta-$1 = scripts/ta_bin_to_c.py --ta $1 \ | ||
--out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c | ||
cleanfiles += $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c | ||
cflags-remove-early-ta-$1-y := -pedantic |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't -pedantic
be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out/arm/core/early_ta_8aaaf200-2450-11e4-abe2-0002a5d5c51b.c:17:8: error: initialization of a flexible array member [-Werror=pedantic]
.ta = {
^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting a __extension__
in front of the const struct early_ta ...
would eliminate the need of removing the -pedantic
flag. It relies on a compiler extension after all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha! I didn't know about this one. Fixed, thanks.
Updated. |
|
Jens' comments addressed and R-b applied.
|
Note: jens' r-b tag is missing on some commits. |
@etienne-lms thanks, I'll take care of adding the missing R-b before merging. |
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Some debug messages have various amounts of leading spaces and dots (.) probably in an attempt to better align the text. It is unreliable because debug traces include function names and line numbers, which introduce random offsets. Remove these characters. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Adds support for `make ta_dev_kit`, to build the user space libraries only and copy them (as well as the related header files and make files) to the export directory. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
In preparation for the introduction of a new TA store type, add a description string to the user_ta_store_ops structure and print it when a user-mode TA is being loaded. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Replace the pointer to the user-mode TA load operations with a list so that several implementations may be used simultaneously. Each store has its own priority. Make tee_ta_init_user_ta_session() iterate on the list and stop as soon as a matching TA is found. This is preparatory work for the introduction of a new TA store. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Early TAs are user-mode Trusted Applications that are embedded at link time in the TEE binary. A special read-only data section is used to store them (.rodata.early_ta). A Python script takes care of converting the TAs into a C source file with the proper linker section attribute. The feature is disabled by default. To enable it, the paths to the TA binaries have to be given in $(EARLY_TA_PATHS). They should be ELF files. Typical build steps: $ make ... CFG_EARLY_TA=y ta_dev_kit # (1) $ # ... build the TAs ... # (2) $ make ... EARLY_TA_PATHS=path/to/<uuid>.stripped.elf # (3) Notes: - Setting CFG_EARLY_TA=y during the first step (1) is not necessary, but it will avoid rebuilding libraries during the third step (3) - CFG_EARLY_TA is automatically enabled when EARLY_TA_PATHS is non-empty in step (3) - Several TAs may be given in $(EARLY_TA_PATHS) (3) Early TAs are given a higher load priority than REE FS TAs, since they should be available even before tee-supplicant is ready. Suggested-by: Zeng Tao <prime.zeng@hisilicon.com> Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Since the parent commit ("Add support for early Trusted Applications"), the link step of tee.elf may pull object files generated from Trusted Application binaries. This is controlled by $(EARLY_TA_PATHS). Adding or removing files should cause tee.elf to be re-linked, even when no re-compilation or change in the configuration variables occur. This is not the case currently. For example: $ make EARLY_TA_PATHS="a.elf b.elf" $ make EARLY_TA_PATHS="a.elf" # Should re-link without b.elf The link recipe is modified so that the link step is forced when the object list changes. Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Import the decompression code from zlib v1.2.11. From the project's README: "zlib 1.2.11 is a general purpose data compression library. [...] The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format)." This code will be used in a later commit to decompress early TAs. Only the inflate() function is needed, and the library is configured without gzip support. The source files that are not required for inflate() are left aside. The library is licensed under a permissive license, see `zlib.h`. Link: http://tools.ietf.org/html/rfc1950 Link: http://tools.ietf.org/html/rfc1951 Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Add decompression code to the early TA loader and update the Python script accordingly. The compression algorithm is "deflate", which is used by zlib and gzip in particular. It allows for compression ratios comprised between 3 (for bigger TAs) and 4.7 (for smaller ones). Those numbers were observed with 32-bit TAs (QEMU). On QEMU (armv7), the code size overhead when CFG_EARLY_TA=y, including the decompressor, is 12K when DEBUG=0 or 20K when DEBUG=1. The decompressor allocates about 39K of heap. Another library compatible with zlib was tried for comparison [1]. The code size overhead with miniz was 8K (DEBUG=0) or 16K (DEBUG=1). On the other hand, the dynamic allocation was about 43K, so the total memory required was about same. Speed was not compared. In the end, zlib was preferred for licensing reasons and because it is widely used. Link: [1] https://github.com/richgel999/miniz Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org> Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (QEMU) Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (QEMUv8, pager) Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (D02 32/64 bits) Tested-by: Jerome Forissier <jerome.forissier@linaro.org> (D02 32/64 bits, pager) Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org> Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
This series implements a feature called "early TAs", which is a way to link Trusted Applications into the TEE binary so that they may be loaded independently of the REE file system and
tee-supplicant
.One use case is being able to invoke a TA from a Linux driver during the boot sequence, before user mode has been spawn. Obviously, In this use case, any service depending on
tee-supplicant
won't be available, but it can be useful anyway.Another use case is to prevent uncontrolled rollback of user TAs. Since TAs are effectively part of the TEE binary, they follow the same life cycle (authentication by the previous stage of th boot loader, controlled updates...).
Note about compression: commit #.6 imports some files from zlib into
core/lib/zlib
. I could probably have re-used what we already have inlib/libzlib
, but I thought that since we had some discussions about possibly removing our (partial) Trusted UI support, this whole directory would probably go away and we would be better off with zlib code under thecore/
folder. I can change that of course.