OP-TEE / optee_os

Trusted side of the TEE
Other
1.56k stars 1.05k forks source link

Porting OP-TEE to Altera CycloneV SoC and for the use with eCos #4115

Closed tstr92 closed 3 years ago

tstr92 commented 3 years ago

Hello,

I am trying to port op-tee to the CycloneV SoC from altera. I have set up the build environment in a ubuntu VM on my windows machine. This environment works as far as i can tell, i can build the op-tee binary. My system starts up with an SPL FSBL which is not aware of OP-TEE, the SPL simply jumps to address 0x00200000 after setting up the system and authenticating a signature. I used the zynq7k platform as a template because to my knowledge, the CycloneV and Zynq7000 are quite similar.

My first goal is to have a running optee_os before I start looking into TA's and the REE counterpart (especially since I intend to use a rtos (eCos) instead of linux). I carefully set the base addresses of SCU, Cache Controller, Interrupt Controller and UART. I created a very simple memory layout platform_config.h:

/* Snoop Control Unit */
#define SCU_BASE        0xFFFEC000

/* Generic Interrupt Controller */
#define GIC_BASE        SCU_BASE
#define GICC_OFFSET     0x100
#define GICD_OFFSET     0x1000
#define GICC_SIZE       0x100
#define GICD_SIZE       0x1000
#define GIC_CPU_BASE        (GIC_BASE + GICC_OFFSET)
#define GIC_DIST_BASE       (GIC_BASE + GICD_OFFSET)

/* Cache Controller */
#define PL310_BASE      0xFFFEF000
#define PL310_SIZE      0x1000

/* UART Console */
#define UART0_BASE      0xFFC02000
#define UART1_BASE      0xFFC03000

#define CONSOLE_UART_BASE   UART0_BASE
#define CONSOLE_UART_CLK_IN_HZ  100000000
#define CONSOLE_BAUDRATE    115200

/*
(...)
Several PL310_*-defines from zynq7k were kept because they are used in main.c
Check out the zynq7k platform for reference. I honestly don't know whether I should keep those or not.
*/

#define TZDRAM_BASE     0x00200000
#define TZDRAM_SIZE     (3 * 1024 * 1024)

#define TEE_RAM_START       TZDRAM_BASE
#define TEE_RAM_PH_SIZE     (1 * 1024 * 1024)

#define TA_RAM_START        (TZDRAM_BASE + TEE_RAM_PH_SIZE)
#define TA_RAM_SIZE     (2 * 1024 * 1024)

#define TEE_SHMEM_START     (TZDRAM_BASE + TEE_RAM_PH_SIZE + TA_RAM_SIZE)
#define TEE_SHMEM_SIZE      (1 * 1024 * 1024)

My UART-Console works and i do get some output:

Hello TEE-World! 16:55:27

D/TC:? get_aslr_seed:1330 Warning: no ASLR seed D/TC:? add_phys_mem:602 VCORE_UNPG_RX_PA type TEE_RAM_RX 0x00200000 size 0x000b1000 D/TC:? add_phys_mem:602 VCORE_UNPG_RW_PA type TEE_RAM_RW 0x002b1000 size 0x0004f000 D/TC:? add_phys_mem:602 TA_RAM_START type TA_RAM 0x00300000 size 0x00200000 D/TC:? add_phys_mem:602 TEE_SHMEM_START type NSEC_SHM 0x00500000 size 0x00100000 D/TC:? add_phys_mem:602 ROUNDDOWN(0xFFC02000, CORE_MMU_PGDIR_SIZE) type IO_NSEC 0xffc00000 size 0x00100000 D/TC:? add_phys_mem:602 ROUNDDOWN((0xFFFEC000 + 0x100), CORE_MMU_PGDIR_SIZE) type IO_SEC 0xfff00000 size 0x00100000 D/TC:? add_phys_mem:602 ROUNDDOWN((0xFFFEC000 + 0x1000), CORE_MMU_PGDIR_SIZE) type IO_SEC 0xfff00000 size 0x00100000 D/TC:? add_phys_mem:615 Physical mem map overlaps 0xfff00000 D/TC:? add_phys_mem:602 ROUNDDOWN(0xFFFEF000, CORE_MMU_PGDIR_SIZE) type IO_SEC 0xfff00000 size 0x00100000 D/TC:? add_phys_mem:615 Physical mem map overlaps 0xfff00000 D/TC:? verify_special_mem_areas:540 No NSEC DDR memory area defined D/TC:? add_va_space:641 type RES_VASPACE size 0x00a00000 D/TC:? add_va_space:641 type SHM_VASPACE size 0x02000000 D/TC:? dump_mmap_table:753 type TEE_RAM_RX va 0x00200000..0x002b0fff pa 0x00200000..0x002b0fff size 0x000b1000 (smallpg) D/TC:? dump_mmap_table:753 type TEE_RAM_RW va 0x002b1000..0x002fffff pa 0x002b1000..0x002fffff size 0x0004f000 (smallpg) D/TC:? dump_mmap_table:753 type SHM_VASPACE va 0x00300000..0x022fffff pa 0x00000000..0x01ffffff size 0x02000000 (pgdir) D/TC:? dump_mmap_table:753 type RES_VASPACE va 0x02300000..0x02cfffff pa 0x00000000..0x009fffff size 0x00a00000 (pgdir) D/TC:? dump_mmap_table:753 type TA_RAM va 0x02d00000..0x02efffff pa 0x00300000..0x004fffff size 0x00200000 (pgdir) D/TC:? dump_mmap_table:753 type NSEC_SHM va 0x02f00000..0x02ffffff pa 0x00500000..0x005fffff size 0x00100000 (pgdir) D/TC:? dump_mmap_table:753 type IO_NSEC va 0x03000000..0x030fffff pa 0xffc00000..0xffcfffff size 0x00100000 (pgdir) D/TC:? dump_mmap_table:753 type IO_SEC va 0x03100000..0x031fffff pa 0xfff00000..0xffffffff size 0x00100000 (pgdir) D/TC:? core_mmu_alloc_l2:265 L2 table used: 1/5 D/TC:? thread_get_id:1004 r0: 00000000 r1: 00000000 spcp: 00000000 tsve: 002D6DB8 ct: FFFF f: 00000001 asve: 00000000 lc: 00000000 E/TC:? assertion 'ct >= 0 && ct < CFG_NUM_THREADS' failed at core/arch/arm/kernel/thread.c:1007 E/TC:0 Panic at core/kernel/assert.c:28 <_assert_break> E/TC:0 TEE load address @ 0x200000 E/TC:0 Call stack: E/TC:0 0x0020b211 E/TC:0 0x002247b3 E/TC:0 0x0022350d E/TC:0 0x002063bb E/TC:0 0x00206771 E/TC:0 0x0021689d E/TC:0 0x002106d3 E/TC:0 0x0021084b E/TC:0 0x00217427 E/TC:0 0x0020feb5 E/TC:0 0x00217639 E/TC:0 0x0021769d E/TC:0 0x0020f591 E/TC:0 0x0020018c

Adding DMSG()-outputs confirms that the assertion ct >= 0 fails. After checking the stacktrace, I realized that this assertion would only be executed in debug mode, because the function check_pa_matches_va is empty when the define CFG_TEE_CORE_DEBUG is not set. I tried running it with CFG_TEE_CORE_DEBUG disabled and then I ran into a data abort. The DFAR contained address 0xffc02008 which is a UART-Register. Apparently, something goes wrong when the cpu tries to use the uart console after some kind of mmu setup. At this point i am quite lost and i would appreciate if someone could point me into the right direction.

Kind regards!


EDIT: I cloned the latest release "3.10.0". It surely is a configuration error on my part. The porting guidelines link to platform-specific-configuration-and-flags. Unfortunately, this resource is not available. Is there some kind of documentation for CFG_*-Settings?

tstr92 commented 3 years ago

Hello, I was able to pin down the problem a little further. Something goes wrong with the MMU initialization during the startup process in optee_os-3.10.0/core/arch/arm/kernel/entry_a32.S. I disabled CFG_CORE_ASLR because I realized that this define causes the console to be reinitialized, which causes a wite access to the UART-Register that I mentioned. The function hi16xx_uart_init, however, only takes the physical address and not the virtual address into account. I might be on the wrong track with this observation, because none of the uart drivers call chip_to_base or phys_to_virt on console_init, but why then do I get this problem in the first place? Now, with CFG_CORE_ASLR disabled, I dont get a data abort, but i am stuck in a loop on uart_flush. This happens directly after the execution of

bl __get_core_pos bl enable_mmu

So it seems that after initializing the mmu, i cant access (uart-) peripheral registers anymore. I am using this line to declare the UART address space as NS memory: register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, HI16XX_UART_REG_SIZE); I thought that this line also makes sure, that i can access the register after mmu init...?

I even tried adding this to hi16xx_uart_init: if (cpu_mmu_enabled()) { base = (paddr_t) phys_to_virt(CONSOLE_UART_BASE, MEM_AREA_IO_NSEC); }

But also here, with CFG_CORE_ASLR both enabled and disabled, I always get stuck in a loop or a data abort on accessing uart registers. Any ideas?


EDIT:

While typing this, I started wondering, whether I should register the UART-Registers as MEM_AREA_IO_SEC. This works. Why is that? Later on, I would like to use the same uart both in the secure and also in the normal world. How can I achieve that?

I will keep posting updates and questions here for the ongoing port to the Cyclone V platform.

jforissier commented 3 years ago

You set CFG_HI16XX_UART=y? Hisilicon UART?

tstr92 commented 3 years ago

Yes, i did. This is my conf.mk so far:

PLATFORM_FLAVOR ?= cyclonev

include core/arch/arm/cpu/cortex-a9.mk

$(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_NUM_THREADS,1) $(call force,CFG_ARM32_core,y) $(call force,CFG_GIC,y) $(call force,CFG_HI16XX_UART,y) $(call force,CFG_WITH_SOFTWARE_PRNG,y) $(call force,CFG_PL310,y) $(call force,CFG_PL310_LOCKED,y) $(call force,CFG_SECURE_TIME_SOURCE_REE,y) $(call force,CFG_CORE_ASLR,n)

CFG_BOOT_SYNC_CPU ?= n CFG_BOOT_SECONDARY_REQUEST ?= n CFG_CRYPTO_SIZE_OPTIMIZATION ?= n CFG_ENABLE_SCTLR_RR ?= y

I set the number of cores and threads to 1 in order to create the simplest working example for a start. I actually have a dual core variant but for the first proof of concept I dont intend to use the second core.

As I said, it does work now when I declare the memory as secure. I can work with that for now, but later on I'd like to use uart in the normal world, too. Now, I get this error: E/TC:0 0 check_phys_mem_is_outside:351 Non-sec mem (0x100000:0x600000) overlaps map (type 17 0:0x2000000) I will try to find the cause myself, but because of this, I need to circle back to my original post: I have been compiling with CFG_TEE_CORE_DEBUG=n in order to avoid the assert error assertion 'ct >= 0 && ct < CFG_NUM_THREADS'. Now, since i need to keep debugging upcoming problems, the stacktrace feature of the debug mode would come in handy. Therefore, I would like to get the assertion fixed. Why would my thread context be -1? (This error happens during execution of check_sec_nsec_mem_config in core_init_mmu_map.)

jforissier commented 3 years ago

$(call force,CFG_TEE_CORE_NB_CORE,1) ... I actually have a dual core variant but for the first proof of concept I dont intend to use the second core.

That is OK as long as you can make sure the second core never enters OP-TEE, of course.

EDIT: While typing this, I started wondering, whether I should register the UART-Registers as MEM_AREA_IO_SEC. This works. Why is that? Later on, I would like to use the same uart both in the secure and also in the normal world. How can I achieve that?

I would think the UART is secure only, and if you declare it MEM_AREA_IO_NSEC that information is recorded in the page table and a non-secure access is issued (even from secure state). So you get an exception. If it is indeed the case that this I/O range is secure only, you won't be able to access it from NS world.

Now, could the secure vs. non-secure property of the UART registers be configurable via TZASC/TZSC or some platform-specific firewall perhaps?

tstr92 commented 3 years ago

Good Point, thank you very much! There are neither TZASC nor TZSC implemented in the Cyclone V but there is a register that controls peripheral security settings. I allowed NS access there and that fixed it.

Could you also take a look at why the assertion might fail in Debug mode?

Now, I get this error: _E/TC:0 0 check_phys_mem_isoutside:351 Non-sec mem (0x100000:0x600000) overlaps map (type 17 0:0x2000000) I will try to find the cause myself, but because of this, I need to circle back to my original post: I have been compiling with _CFG_TEE_COREDEBUG=n in order to avoid the assert error assertion 'ct >= 0 && ct < CFG_NUM_THREADS'. Now, since i need to keep debugging upcoming problems, the stacktrace feature of the debug mode would come in handy. Therefore, I would like to get the assertion fixed. Why would my thread context be -1? (This error happens during execution of _check_sec_nsec_memconfig in _core_init_mmumap.)

Also, I was not completely on the wrong track. I activated CFG_CORE_ASLR again and then we still get stuck with the uart registers. This is because hi16xx_uart_init does not convert the base address to a virtual address. I propose the following addtion to the init function, before the register access is made: base = (paddr_t) chip_to_base(&pd->chip); This fixes at least the problem that i was having.

tstr92 commented 3 years ago

Hello @jforissier After some fiddling, OP-TEE finally finishes initializations and switches to normal world: I/TC: Primary CPU switching to normal world boot

Unfortunately, the processor dies instantly on returning to normal world, because any access to the FPGA-ROM leads to a translation fault after OP-TEE enables the MMU. How I can setup a desired memory map for normal world code execution?

Some Info about my System: I implemented secure boot by forcing the boot rom to jump into the fpga address space for executing the preloader code. The FPGA-ROM starts at 0xC0000000 and has a size of 128KB. OP-TEE as well as the normal world OS eCos are located on QSPI-Flash and loaded to ddr memory by the preloader. These binaries are signed with a private key and authenticated before execution. Once the OP-TEE-binary is authenticated, the preloader jumps to the OP-TEE entry point.

Since I am not using a GPOS like Linux, but instead the rtos ecos, I dont have the need to use virtual addresses at all. The sdram controller offers the possibilities to segment the ddr memory into secure, non-secure and shared areas. Additionally, bus masters and slaves can be setup to accept only secure or non-secure transactions. I would like to setup the required permission for my system by these means and avoid virtualizing the memory map with the mpu. Is that possible? I would like to have the following config: 0xC0000000: Preloader Load Address (FPGA-ROM) 0x00200000: ecos Load Address (DDR Memory) 0x00700000: OP-TEE Load Address (DDR Memory) VA = PA everywhere

Current Config:

D/TC:? dump_mmap_table:753 type TEE_RAM_RX va 0x00700000..0x00747fff pa 0x00700000..0x00747fff size 0x00048000 (smallpg) D/TC:? dump_mmap_table:753 type TEE_RAM_RW va 0x00748000..0x007fffff pa 0x00748000..0x007fffff size 0x000b8000 (smallpg) D/TC:? dump_mmap_table:753 type SHM_VASPACE va 0x00800000..0x027fffff pa 0x00000000..0x01ffffff size 0x02000000 (pgdir) D/TC:? dump_mmap_table:753 type RES_VASPACE va 0x02800000..0x031fffff pa 0x00000000..0x009fffff size 0x00a00000 (pgdir) D/TC:? dump_mmap_table:753 type TA_RAM va 0x03200000..0x033fffff pa 0x00800000..0x009fffff size 0x00200000 (pgdir) D/TC:? dump_mmap_table:753 type NSEC_SHM va 0x03400000..0x034fffff pa 0x00a00000..0x00afffff size 0x00100000 (pgdir) D/TC:? dump_mmap_table:753 type IO_NSEC va 0x03500000..0x035fffff pa 0xffc00000..0xffcfffff size 0x00100000 (pgdir) D/TC:? dump_mmap_table:753 type IO_SEC va 0x03600000..0x036fffff pa 0xfff00000..0xffffffff size 0x00100000 (pgdir)

jforissier commented 3 years ago

Since I am not using a GPOS like Linux, but instead the rtos ecos, I dont have the need to use virtual addresses at all.

OK, but I suppose you could still easily create an identity mapping in the normal world OS to solve this problem?

tstr92 commented 3 years ago

OK, but I suppose you could still easily create an identity mapping in the normal world OS to solve this problem?

What is that and how would I do that? Also, when OP-TEE restores the context from before startup of OP-TEE (in my case code execution from FPGA-ROM) after initialization, how do I tell it, that the corresponding address space starting at 0xC0000000 needs to be available when OP-Tee returns? Similarly, how do i register normal world RX and RW Memory in OP-TEE?

jenswi-linaro commented 3 years ago

OK, but I suppose you could still easily create an identity mapping in the normal world OS to solve this problem?

What is that and how would I do that?

That's VA=PA mapping

Also, when OP-TEE restores the context from before startup of OP-TEE (in my case code execution from FPGA-ROM) after initialization, how do I tell it, that the corresponding address space starting at 0xC0000000 needs to be available when OP-Tee returns?

When OP-TEE is entered CPU is still executing in secure mode (ns-bit cleared). When OP-TEE exits via the secure monitor it normally does a return from exception into non-secure mode (ns-bit set). MMU is normally not enabled in non-secure mode at this stage. So depending on the non-secure software it might be enough to supply the address of the first non-secure instruction to execute in r1 before entering OP-TEE.

Similarly, how do i register normal world RX and RW Memory in OP-TEE?

One way of doing that is using the register_ddr() macro like in core/arch/arm/plat-vexpress/main.c for instance.

tstr92 commented 3 years ago

@jenswi-linaro Thank you! You're right, the debugger also tells me that the MMU is disabled on return. I blamed OP-TEE because I did not fully understand what was going on. But now, I figured out why I get a fault: The Code I return to is Thumb code but when I return, the Processor is in ARM mode. That is weird, because when I inspect the registers just before rfeia sp! is executed, sp points to 0x0076c9b0 which contains the correct return address 0xc0004cff. The Thumb Code gets interpreted as ARM Code which (eventually) leads to the execution of an undefined instruction.

Now, why would the processor not change back to Thumb mode after executing rfeia sp!?

jenswi-linaro commented 3 years ago

You need to update SPSR also. That's normally handled by init_sec_mon(), but perhaps you're booting differently.

tstr92 commented 3 years ago

You need to update SPSR also. That's normally handled by init_sec_mon(), but perhaps you're booting differently.

To be honest, i am not sure what booting normally would mean for optee. In my case, the preloader loads the optee_os binary to memory and jumps to _start from entry_a32.s via a blx instruction. I verified that init_sec_mon is part of the bootup sequence and it definitely gets called. Do I have to override it as it is done in plat-ti?

jenswi-linaro commented 3 years ago

I'm sorry, I accidentally wrote r1 above, I meant lr. The boot arguments for OP-TEE are described in entry_a32.S as:

         /*
         * Save boot arguments
         * entry r0, saved r4: pagestore
         * entry r1, saved r7: (ARMv7 standard bootarg #1)
         * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2)
         * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0)
         */

So what's in lr is going to be used as the address returning to in non-secure world.

Is the memory at 0xc0004cff secure or non-secure memory? If it's secure then I guess you're really getting a prefetch abort first and then perhaps an undefined instruction after jumping to the non-secure exception vector (VBAR).

tstr92 commented 3 years ago

This address space is a ROM-Memory located inside the FPGA. I did not specifically declare it as secure. I did not yet find any information about the default securtiy state, but i am confident that it is non-secure. The next four bytes at the return address disassemble to a branch instruction (when interpreted as ARM Code instead of as two separate Thumb instructions). The offset of this branch is consistent with the next address the processor goes to. At that address the processor dies. This is what i meant by eventually.


         /*
         * Save boot arguments
         * entry r0, saved r4: pagestore
         * entry r1, saved r7: (ARMv7 standard bootarg #1)
         * entry r2, saved r6: device tree address, (ARMv7 standard bootarg #2)
         * entry lr, saved r5: non-secure entry address (ARMv7 bootarg #0)
         */

Maybe the problem lies in the fact that I have not supplied anything in r0-r2. What exactly do I need here?

jenswi-linaro commented 3 years ago

r0-r2 are probably ignored in this case.

tstr92 commented 3 years ago

I am using a workaround now: I am compiling the module that jumps to TEE with -marm to avoid the mode change problem. Also, I provide the start address of the non-Secure World software in the LR so that I don't return to the preloader. This works and after returning from TEE, the processor successfully executes my bare-metal demo program.

My next step is to replace the bare-metal program with ecos. Now, ecos does a fair bit of low level initializations and I am unsure of what the OS is allowed and/or supposed to do in order to work together with op-tee. I think that MMU- and Cache-related stuff is critical here. (What else is?) Is there any documentation on the startup tasks of op-tee ad the OS? At the moment, my ecos-system dies trying to write to the ACTLR.

tstr92 commented 3 years ago

Should I open separate issues for these two poblems:

  1. Assertion failure with CFG_TEE_CORE_DEBUG enabled:

    E/TC:? assertion 'ct >= 0 && ct < CFG_NUM_THREADS' failed at core/arch/arm/kernel/thread.c:1007 E/TC:0 Panic at core/kernel/assert.c:28 <_assert_break>

  2. RFE (return from TEE init) does not change back to ARM mode. Code is misinterpreted and CPU dies.

I've worked around these issues, but I haven't fixed them.

jenswi-linaro commented 3 years ago

Should I open separate issues for these two poblems

I'm not sure that you'd get much more help from that. I suspect that the problems originates from your port in some way.

jforissier commented 3 years ago

D/TC:? get_aslr_seed:1330 Warning: no ASLR seed

One thing I noticed: the interrogation mark is unexpected here, it should be the core number for the boot CPU instead (usually 0). It shows that thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR is false, in other words exceptions should be masked but they aren't.

tstr92 commented 3 years ago

Thank you; I disabled Interrupts before starting op-tee now and the question mark changed to a 0. This did not fix the assertion failure though. Which other assumptions does op-tee make of the system state on startup?

tstr92 commented 3 years ago

Is it allowed for the normal world software to setup GIC, MMU, Cache etc.? That is, what ecos is doing and where the CPU dies. Or should these be set up in op-tee and never be touched again?

jenswi-linaro commented 3 years ago

GIC, MMU and internal Cache should be more or less as usual. If you have an external cache it's usually mostly configured by secure world.

tstr92 commented 3 years ago

Alright, i have got ecos running now. Later on, I will have to verify all of these hardware setups, but for now, I will move on.

Just to clarify, because I am still not sure about the MMU config (or hw config in general) and I will need to come back to this topic for verification: I read, that the normal world and the secure world each work with different MMU page tables and therefore VAs are not compatible between worlds. Is that correct? Then, how do we enforce the memory access restrictions from normal world to secure world?

My next step would be the client side running in ecos. @jforissier: In issue #2930 you suggested the poster, who worked on a similar problem, to

look at the Linux driver (drivers/tee/optee), which is obviously where the normal world OS interfaces with OP-TEE. This should help you identify what is needed to have OP-TEE work with FreeRTOS.

I suppose the same is valid for me, so I will look into it. In the meantime, could you tell me whether I have to go higher up (e.g. to /drivers/tee)? I will probably need the file arm-smccc.h. Is there a way to get these resources under the BSD license instead of GPL?

Then as a second step you may need to port the GlobalPlatform TEE Client API (libteec), that is, if you need to have user-space client applications (not sure how this applies to FreeRTOS). Note that there is a kernel client API in the Linux driver, perhaps you don't need more that that.

That would be optee-client, wouldn't it? I will evaluate, whether porting is necessary for my purposes as the next step then.

I have contacted the original poster; Unfortunately, he abandoned the idea and could not help me on this.

jenswi-linaro commented 3 years ago

Just to clarify, because I am still not sure about the MMU config (or hw config in general) and I will need to come back to this topic for verification: I read, that the normal world and the secure world each work with different MMU page tables and therefore VAs are not compatible between worlds. Is that correct? Then, how do we enforce the memory access restrictions from normal world to secure world?

That's where the ns-bit comes into the picture. It's always set (implicitly enforced by hardware) for mappings while in non-secure mode, in secure mode it can be specified in the translation tables. If ns-bit is set access to trustzone protected devices/memory is blocked, usually results in an external abort.

My next step would be the client side running in ecos. @jforissier: In issue #2930 you suggested the poster, who worked on a similar problem, to

look at the Linux driver (drivers/tee/optee), which is obviously where the normal world OS interfaces with OP-TEE. This should help you identify what is needed to have OP-TEE work with FreeRTOS.

I suppose the same is valid for me, so I will look into it. In the meantime, could you tell me whether I have to go higher up (e.g. to /drivers/tee)? I will probably need the file arm-smccc.h. Is there a way to get these resources under the BSD license instead of GPL?

Then as a second step you may need to port the GlobalPlatform TEE Client API (libteec), that is, if you need to have user-space client applications (not sure how this applies to FreeRTOS). Note that there is a kernel client API in the Linux driver, perhaps you don't need more that that.

That would be optee-client, wouldn't it? I will evaluate, whether porting is necessary for my purposes as the next step then.

I have contacted the original poster; Unfortunately, he abandoned the idea and could not help me on this.

Another option is to look at U-Boot instead. I've written the initial patches and can release them again under a BSD license if that helps.

tstr92 commented 3 years ago

I've written the initial patches and can release them again under a BSD license if that helps.

That would help, thank you!

jenswi-linaro commented 3 years ago

I've written the initial patches and can release them again under a BSD license if that helps.

That would help, thank you!

So you've looked at the U-Boot driver and think it would make sense to copy that code?

tstr92 commented 3 years ago

Yes, i have looked at the uboot repository. It looks like there are fewer dependencies in the U-Boot driver than in the linux driver and some parts of it seem to be kept a little simpler, which probably makes it easier to port to ecos. It will still be quite some effort, but it would be great to have this resource available under the bsd license.

Since device drivers in ecos work differently than in linux and u-boot and the target platform is fixed, i am thinking of simplifying the driver to some kind of worker task, do you think this is a viable idea?

Let me recap what I understand of this driver so far, maybe you can correct if I am misunderstanding something:

I also have some questions:

tstr92 commented 3 years ago

I have started porting the U-Boot sources already, and I wanted to test the context switching mechanisms by calling the pseudo TA invoke_tests.pta. Unfortunately, I got stuck during the open_session procedure, because the pseudo TA sends the command OPTEE_MSG_RPC_CMD_GET_TIME back to me, which is not implemented in U-Boot. Maybe the U-Boot-Tee-Driver is simpler to port, because it is not fully featured?! Where does it make sense to continue from here? This is the output I am getting so far:

(... optee init ...) I/TC: Primary CPU switching to normal world boot !!! SMC CALL NOW !!! tmain_task Hello non-Secure World! optee_task OP-TEE: revision 3.10 D/TC:0 tee_entry_exchange_capabilities:102 Dynamic shared memory is enabled so far, so good. waiting for commands... rc0 00000000 rc1 00000000 D/TC:? 0 tee_ta_init_pseudo_ta_session:283 Lookup pseudo TA d96a5b40-c3e5-21e3-8794-1002a5d5c61b a0=ffff0004 a1=00000000 a2=00000000 a3=00000000 D/TC:? 0 tee_ta_init_pseudo_ta_session:296 Open invoke_tests.pta a0=ffff0004 a1=00000000 a2=00000000 a3=00000000 D/TC:? 0 tee_ta_init_pseudo_ta_session:310 invoke_tests.pta : d96a5b40-c3e5-21e3-8794-1002a5d5c61b a0=ffff0004 a1=00000000 a2=00000000 a3=00000000 D/TC:? 0 create_ta:384 create entry point for pseudo TA "invoke_tests.pta" a0=ffff0004 a1=00000000 a2=00000000 a3=00000000 D/TC:? 0 open_session:397 open entry point for pseudo ta "invoke_tests.pta" a0=ffff0004 a1=00000000 a2=00000000 a3=00000000 a0=ffff0000 a1=000000a0 a2=00000000 a3=00000000 alloc!!! a0=ffff0005 a1=00000000 a2=0041c270 a3=00000000 TEE_ERROR_NOT_IMPLEMENTED (arg->cmd=00000003) a0=ffff0002 a1=00000000 a2=0041c270 a3=00000000

jenswi-linaro commented 3 years ago

Here's the patches. patches.tar.gz

jenswi-linaro commented 3 years ago

I have started porting the U-Boot sources already, and I wanted to test the context switching mechanisms by calling the pseudo TA _invoketests.pta. Unfortunately, I got stuck during the _opensession procedure, because the pseudo TA sends the command _OPTEE_MSG_RPC_CMD_GETTIME back to me, which is not implemented in U-Boot. Maybe the U-Boot-Tee-Driver is simpler to port, because it is not fully featured?!

Yes, it's a bit limited.

Where does it make sense to continue from here?

Implement the missing services.

jenswi-linaro commented 3 years ago

Since device drivers in ecos work differently than in linux and u-boot and the target platform is fixed, i am thinking of simplifying the driver to some kind of worker task, do you think this is a viable idea?

I'm not sure what you mean by worker task.

Let me recap what I understand of this driver so far, maybe you can correct if I am misunderstanding something:

  • In the beginning, _opteeprobe is called in order to make sure optee is installed correctly. This I could do on task startup.
  • In the case of my Cortex-A9, there is no hvc-call, so I can always invoke the smc call which removes the need for _dev_getplatdata, _get_invokefunc and _optee_ofdata_toplatdata.
  • I can start a session using _optee_opensession, communicate with the TEE via _optee_invokefunc as long as the session is open and close the session with _optee_closesession.

Makes sense

  • The supplicant lets the Tee request a service from the OS. (What would that be in practice?)

See https://github.com/OP-TEE/optee_os/blob/master/core/include/optee_rpc_cmd.h, some parts are optional depending on your configuration.

I also have some questions:

  • What exactly does rpmb.c do?
  • What if I don't have an MMC Device? Can I remove the MMC deps?

That can be removed then.

tstr92 commented 3 years ago

This is great, thank you very much @jenswi-linaro !! I can now communicate with the pseudo TA invoke_tests.pta and I am implementing testcalls in order to verify my setup. Thanks again everyone, you have been very helpful!

I'm not sure what you mean by worker task.

I mean a task that waits for request flags to be set and then makes the call to the secure world.

github-actions[bot] commented 3 years ago

This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

meanarchist commented 4 months ago

Hey @tstr92 Were you able to port it to Altera CycloneV SoC?