github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/load.go (about)

     1  // Copyright 2022 The Armored Witness OS authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"fmt"
    19  	"log"
    20  
    21  	"github.com/usbarmory/tamago/arm"
    22  	"github.com/usbarmory/tamago/bits"
    23  	"github.com/usbarmory/tamago/soc/nxp/imx6ul"
    24  
    25  	"github.com/usbarmory/armory-boot/exec"
    26  
    27  	"github.com/usbarmory/GoTEE/monitor"
    28  )
    29  
    30  const (
    31  	// Watchdog interval (in ms) to force context switching (User -> System mode)
    32  	// to prevent Trusted Applet starvation of Trusted OS resources.
    33  	watchdogTimeout = 60 * 1000
    34  
    35  	// watchdogWarningInterval (in ms) controls how long before the watchdog triggers
    36  	// the service request interrupt will be raised.
    37  	watchdogWarningInterval = 5 * 1000
    38  )
    39  
    40  // loadApplet loads a TamaGo unikernel as trusted applet.
    41  func loadApplet(elf []byte, ctl *controlInterface) (ta *monitor.ExecCtx, err error) {
    42  	image := &exec.ELFImage{
    43  		Region: appletRegion,
    44  		ELF:    elf,
    45  	}
    46  
    47  	// BEE requires caching to be activated before image loading
    48  	imx6ul.ARM.ConfigureMMU(uint32(image.Region.Start()), uint32(image.Region.End()), 0, arm.MemoryRegion)
    49  
    50  	if err = image.Load(); err != nil {
    51  		return
    52  	}
    53  
    54  	if ta, err = monitor.Load(image.Entry(), image.Region, true); err != nil {
    55  		return nil, fmt.Errorf("SM could not load applet: %v", err)
    56  	}
    57  
    58  	log.Printf("SM applet loaded addr:%#x entry:%#x size:%d", ta.Memory.Start(), ta.R15, len(elf))
    59  
    60  	// register RPC receiver
    61  	ta.Server.Register(ctl.RPC)
    62  	ctl.RPC.Ctx = ta
    63  
    64  	// set stack pointer to end of available memory
    65  	ta.R13 = uint32(ta.Memory.End())
    66  
    67  	// override default handler
    68  	ta.Handler = handler
    69  	ta.Debug = true
    70  
    71  	// enable FIQs
    72  	bits.Clear(&ta.SPSR, CPSR_FIQ)
    73  
    74  	return ta, run(ta)
    75  }
    76  
    77  func run(ctx *monitor.ExecCtx) (err error) {
    78  	mode := arm.ModeName(int(ctx.SPSR) & 0x1f)
    79  	ns := ctx.NonSecure()
    80  
    81  	log.Printf("SM applet started mode:%s sp:%#.8x pc:%#.8x ns:%v", mode, ctx.R13, ctx.R15, ns)
    82  
    83  	irqHandler[imx6ul.WDOG2.IRQ] = func() {
    84  		imx6ul.WDOG2.Service(watchdogTimeout)
    85  	}
    86  
    87  	// activate watchdog to prevent resource starvation
    88  	imx6ul.GIC.EnableInterrupt(imx6ul.WDOG2.IRQ, true)
    89  	imx6ul.WDOG2.EnableInterrupt(watchdogWarningInterval)
    90  	imx6ul.WDOG2.EnableTimeout(watchdogTimeout)
    91  
    92  	// route IRQs as FIQs to serve them through applet handler
    93  	imx6ul.GIC.FIQEn(true)
    94  
    95  	err = ctx.Run()
    96  
    97  	// restore routing to IRQ handler
    98  	imx6ul.GIC.FIQEn(false)
    99  
   100  	// Re-enable interrupts as the monitor exception handler disables them
   101  	// when switching back to System Mode.
   102  	imx6ul.ARM.EnableInterrupts(false)
   103  
   104  	log.Printf("SM applet stopped mode:%s sp:%#.8x lr:%#.8x pc:%#.8x ns:%v err:%v", mode, ctx.R13, ctx.R14, ctx.R15, ns, err)
   105  
   106  	if err != nil && debug {
   107  		err = inspect(taELF, ctx)
   108  	}
   109  
   110  	return
   111  }