### Run TamaGo Example Application with QEMU Emulation Source: https://github.com/usbarmory/tamago/wiki/Home This sequence of commands clones the TamaGo example application repository, navigates into its directory, and then uses 'make qemu' to launch an emulated run of the application. This is useful for testing and debugging without requiring physical hardware. ```shell git clone https://github.com/usbarmory/tamago-example cd tamago-example && make qemu ``` -------------------------------- ### Start openocd and Debug with GDB Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/mx6ullevk/README.md This sequence demonstrates starting the openocd daemon with specific interface and target configurations, connecting to its command line via telnet, and then initiating a GDB debugging session using a gdbinit file. ```sh # start openocd daemon openocd -f interface/ftdi/jtagkey.cfg -f target/imx6ul.cfg -c "adapter speed 1000" # connect to the OpenOCD command line telnet localhost 4444 # debug with GDB arm-none-eabi-gdb -x gdbinit main ``` -------------------------------- ### Importing Board Package in Go Application Source: https://github.com/usbarmory/tamago/wiki/Home Example of how to import a board-specific package in a Go application. This import ensures that the necessary hardware initialization and runtime support for the target board (e.g., USB armory Mk II) are included during compilation. ```go import ( // Example for USB armory Mk II _ "github.com/usbarmory/tamago/board/usbarmory/mk2" ) ``` -------------------------------- ### Compiling Go Applications for Tamago (arm64) Source: https://github.com/usbarmory/tamago/wiki/Home Example compilation command for a Go application targeting the 8MPLUSLPD4-EVK using the `arm64` architecture. It sets `GOOS` and `GOARCH`, uses the `TAMAGO` compiler, and specifies linker flags for memory addresses. ```sh # set this library as `runtime/goos` overlay export GOOSPKG=github.com/usbarmory/tamago # Example for 8MPLUSLPD4-EVK GOOS=tamago GOARCH=arm64 ${TAMAGO} build -ldflags "-T 0x40010000 -R 0x1000" main.go ``` -------------------------------- ### Compiling Go Applications for Tamago (riscv64) Source: https://github.com/usbarmory/tamago/wiki/Home Example compilation command for a Go application targeting QEMU RISC-V sifive_u using the `riscv64` architecture. It sets `GOOS` and `GOARCH`, uses the `TAMAGO` compiler, and specifies linker flags for memory addresses. ```sh # set this library as `runtime/goos` overlay export GOOSPKG=github.com/usbarmory/tamago # Example for QEMU RISC-V sifive_u GOOS=tamago GOARCH=riscv64 ${TAMAGO} build -ldflags "-T 0x80010000 -R 0x1000" main.go ``` -------------------------------- ### Compiling Go Applications for Tamago (amd64) Source: https://github.com/usbarmory/tamago/wiki/Home Example compilation command for a Go application targeting Cloud Hypervisory, QEMU, and Firecracker KVMs using the `amd64` architecture. It sets the `GOOS` and `GOARCH` environment variables, uses the `TAMAGO` compiler, and specifies linker flags for memory addresses. ```sh # set this library as `runtime/goos` overlay export GOOSPKG=github.com/usbarmory/tamago # Example for Cloud Hypervisory, QEMU and Firecracker KVMs GOOS=tamago GOARCH=amd64 ${TAMAGO} build -ldflags "-T 0x10010000 -R 0x1000" main.go ``` -------------------------------- ### Initialize USB Armory Mk II Board with Tamago Go Source: https://context7.com/usbarmory/tamago/llms.txt Provides a complete board initialization sequence for the USB Armory Mk II single-board computer using the `tamago/board/usbarmory/mk2` package. It demonstrates how to automatically initialize hardware upon package import and access various peripheral instances like UART, USB controllers, SD/MMC controllers, and I2C controllers. The example also shows how to configure bus widths for SD/MMC and notes the availability of Ethernet on specific models. ```go package main import ( // Auto-initializes hardware on import _ "github.com/usbarmory/tamago/board/usbarmory/mk2" "github.com/usbarmory/tamago/board/usbarmory/mk2" ) func main() { // Get board model modelNum, modelName := mk2.Model() println("Model:", modelName) // Access peripheral instances // UART serial ports mk2.UART1.Init() mk2.UART2.Init() // USB controllers mk2.USB1.Init() mk2.USB2.Init() // SD/MMC controllers mk2.USDHC1.Init(4) // 4-bit bus width mk2.USDHC2.Init(8) // 8-bit bus width for eMMC // I2C controllers mk2.I2C1.Init() mk2.I2C2.Init() // Ethernet (LAN model only) // mk2.ENET2 available on USB armory Mk II LAN } ``` -------------------------------- ### Compiling Go Applications for Tamago (arm) Source: https://github.com/usbarmory/tamago/wiki/Home Example compilation command for a Go application targeting the USB armory Mk II using the `arm` architecture (ARMv7). It sets `GOOS`, `GOARM`, `GOARCH`, uses the `TAMAGO` compiler, and specifies linker flags. ```sh # set this library as `runtime/goos` overlay export GOOSPKG=github.com/usbarmory/tamago # Example for USB armory Mk II GOOS=tamago GOARM=7 GOARCH=arm ${TAMAGO} build -ldflags "-T 0x80010000 -R 0x1000" main.go ``` -------------------------------- ### Control NXP USB Controller with Tamago Go Source: https://context7.com/usbarmory/tamago/llms.txt Demonstrates the control of NXP USB PHY controllers in device mode using the `tamago/soc/nxp/imx6ul` package. This example covers initializing the USB controller, checking the connection speed, enabling and clearing interrupts, handling bus resets, and controlling the run/stop state of the controller. It also includes functionality for powering down the USB PHY. ```go package main import ( "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { // Initialize USB controller usb := imx6ul.USB1 usb.Init() // Check connection speed speed := usb.Speed() println("USB Speed:", speed) // "full", "low", or "high" // Enable interrupt for specific events usb.EnableInterrupt(0) // IRQ_UI - USB Interrupt // Clear interrupt usb.ClearInterrupt(0) // Wait for and handle bus reset usb.Reset() // Run/Stop controller usb.Run() usb.Stop() // Power down USB PHY usb.PowerDown() } ``` -------------------------------- ### Run Tamago with QEMU and Network Device Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/microvm/README.md This command launches QEMU with a paravirtualized network device (virtio-net-device) connected to a TAP interface. The '-kernel' flag specifies the kernel image to boot. This setup is essential for network communication in the virtualized environment. ```sh -device virtio-net-device,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ -kernel example ``` -------------------------------- ### Initialize Firecracker MicroVM Board with Tamago Go Source: https://context7.com/usbarmory/tamago/llms.txt Shows how to initialize a Firecracker microVM environment with AMD64 support using the `tamago/board/firecracker/microvm` package. This example demonstrates accessing the AMD64 CPU, initializing Symmetric Multiprocessing (SMP) with all available cores, configuring serial output via COM1, and setting up the I/O APIC for interrupt routing, specifically routing the VirtIO network interrupt. ```go package main import ( // Auto-initializes hardware on import _ "github.com/usbarmory/tamago/board/firecracker/microvm" "github.com/usbarmory/tamago/board/firecracker/microvm" ) func main() { // Access peripheral instances cpu := microvm.AMD64 // Initialize SMP with all available cores cpu.InitSMP(-1) // Serial output via COM1 uart := microvm.UART0 uart.Write([]byte("Hello from Firecracker!\n")) // I/O APIC for interrupt routing ioapic := microvm.IOAPIC0 // Route VirtIO network interrupt ioapic.Route(microvm.VIRTIO_NET0_IRQ, 0, false) } ``` -------------------------------- ### Running and Debugging with QEMU Source: https://github.com/usbarmory/tamago/blob/master/board/usbarmory/README.md This snippet demonstrates how to execute the Tamago target under QEMU emulation and how to debug it using GDB. It includes the command to start the QEMU system emulator and the command to connect GDB to the emulated target. ```sh qemu-system-arm \ -machine mcimx6ul-evk -cpu cortex-a7 -m 512M \ -nographic -monitor none -serial null -serial stdio \ -kernel main -semihosting ``` ```sh arm-none-eabi-gdb -ex "target remote 127.0.0.1:1234" main ``` ```gdb b ecdsa.Verify continue ``` -------------------------------- ### Configure UART Serial Communication with NXP Drivers Go Source: https://context7.com/usbarmory/tamago/llms.txt Details the configuration and usage of NXP UART controllers for serial communication, including RS-232 mode, using the `tamago/soc/nxp/uart` and `tamago/soc/nxp/imx6ul` packages. The example illustrates using pre-configured UART instances from the SoC package or creating custom UART instances with specific parameters like base address, clocking, baud rate, and flow control. It covers initialization, transmitting and receiving single characters or buffers, and enabling/disabling the UART. ```go package main import ( "github.com/usbarmory/tamago/soc/nxp/uart" "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { // Use pre-configured UART from SoC package serial := imx6ul.UART2 // Or create custom UART instance serial = &uart.UART{ Index: 2, Base: 0x021e8000, CCGR: imx6ul.CCM_CCGR0, CG: 14, Clock: imx6ul.GetUARTClock, Baudrate: 115200, DTE: false, // DCE mode Flow: false, // No hardware flow control } // Initialize UART serial.Init() // Transmit single character serial.Tx('H') serial.Tx('i') serial.Tx('\n') // Write buffer n, _ := serial.Write([]byte("Hello, UART!\n")) println("Wrote", n, "bytes") // Receive single character char, valid := serial.Rx() if valid { println("Received:", char) } // Read into buffer buf := make([]byte, 64) n, _ = serial.Read(buf) println("Read", n, "bytes") // Disable/Enable UART serial.Disable() serial.Enable() } ``` -------------------------------- ### Compiling and Running TamaGo Example in Linux Userspace (Shell) Source: https://github.com/usbarmory/tamago/blob/master/user/linux/README.md This shell command demonstrates how to compile and run a TamaGo application in Linux userspace. It sets the necessary environment variables (GOOS, GOOSPKG, GOARCH) and uses the 'tamago run' command to execute the Go program, showcasing the output with error messages due to isolation. ```sh # GOOSPKG can be omitted to use Go compiler default overlay GOOS=tamago GOOSPKG=github.com/usbarmory/tamago GOARCH=amd64 \ $TAMAGO run test.go ** I can't get out! ;-( ** dial tcp 8.8.8.8:53: net.SocketFunc is nil ** I can't get out! ;-( ** open /etc/passwd: No such file or directory ``` -------------------------------- ### Raspberry Pi Firmware Configuration Source: https://github.com/usbarmory/tamago/blob/master/board/raspberrypi/README.md An example `config.txt` file for Raspberry Pi to enable UART, set the kernel to load, and specify the kernel address. This configuration is essential for the TamaGo-built binary to be loaded and executed by the Pi firmware. ```ini enable_uart=1 uart_2ndstage=1 dtparam=uart0=on kernel=main.bin kernel_address=0x8000 disable_commandline_tags=1 core_freq=250 ``` -------------------------------- ### TamaGo Userspace Network and File Access Isolation Example (Go) Source: https://github.com/usbarmory/tamago/blob/master/user/linux/README.md This Go code demonstrates TamaGo's userspace execution by attempting to perform network dial and file read operations. It shows that these operations fail due to the isolation provided by TamaGo, as indicated by the 'net.SocketFunc is nil' and 'No such file or directory' errors. ```go package main import ( "fmt" "net" "os" _ "github.com/usbarmory/tamago/user/linux" ) func main() { _, err := net.Dial("tcp", "8.8.8.8:53") fmt.Printf("** I can't get out! ;-( ** %s\n", err) _, err = os.ReadFile("/etc/passwd") fmt.Printf("** I can't get out! ;-( ** %s\n", err) } ``` -------------------------------- ### Configure and Use ARM Generic Timers in Go Source: https://context7.com/usbarmory/tamago/llms.txt This Go code configures and utilizes ARM generic timers for timing and alarm functionalities. It initializes the timers, reads the counter, gets and sets system time in nanoseconds, and manages alarms. It also includes a busy-wait loop. ```go package main import ( "github.com/usbarmory/tamago/arm" "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { cpu := imx6ul.ARM // Initialize generic timers (base address, frequency) cpu.InitGenericTimers(0x00a00000, 8000000) // 8 MHz // Read counter value counter := cpu.Counter() println("Counter:", counter) // Get system time in nanoseconds ns := cpu.GetTime() println("Time:", ns, "ns") // Set system time cpu.SetTime(0) // Reset to 0 // Set alarm (generates interrupt at expiration) alarmNs := int64(1000000000) // 1 second from now cpu.SetAlarm(cpu.GetTime() + alarmNs) // Cancel alarm cpu.SetAlarm(0) // Busyloop for busy waiting arm.Busyloop(1000000) } ``` -------------------------------- ### Execute MicroVM with Firecracker Source: https://github.com/usbarmory/tamago/blob/master/board/firecracker/microvm/README.md This command starts a Firecracker microVM using a provided configuration file. The TamaGo ELF image would be specified within this configuration. ```sh firecracker --config-file vm_config.json ``` -------------------------------- ### GIC Interrupt Service Routine (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Handles hardware interrupts using the Generic Interrupt Controller (GIC) on ARM processors. Initializes the GIC, enables interrupts, and starts a goroutine to service them. ```go package main import ( "github.com/usbarmory/tamago/arm" "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { cpu := imx6ul.ARM gic := imx6ul.GIC // Initialize GIC gic.Init() // Enable specific interrupt gic.EnableInterrupt(imx6ul.USB1_IRQ, false) // Enable CPU interrupts cpu.EnableInterrupts(false) // Start interrupt service goroutine go arm.ServiceInterrupts(func() { // Get pending interrupt irq, _ := gic.GetInterrupt(false) // Handle interrupt based on IRQ number switch irq { case imx6ul.USB1_IRQ: // Handle USB interrupt println("USB interrupt received") } // Acknowledge interrupt gic.ClearInterrupt(irq) }) // Main loop continues while interrupts are serviced select {} } ``` -------------------------------- ### GDB Debugging with OpenOCD Source: https://github.com/usbarmory/tamago/blob/master/board/usbarmory/README.md This section details how to debug the application using GDB over JTAG with openocd. It includes the necessary gdbinit configuration and commands to start openocd, connect to its command line, and initiate a GDB session. ```sh # start openocd daemon openocd -f interface/ftdi/jtagkey.cfg -f target/imx6ul.cfg -c "adapter speed 1000" # connect to the OpenOCD command line telnet localhost 4444 # debug with GDB arm-none-eabi-gdb -x gdbinit main ``` ```gdb target remote localhost:3333 set remote hardware-breakpoint-limit 6 set remote hardware-watchpoint-limit 4 ``` ```gdb hb ecdsa.Verify continue ``` -------------------------------- ### Initialize AMD64 CPU with SMP Support (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Provides symmetric multiprocessing (SMP) support for x86-64 processors, including Local APIC configuration. It initializes the Bootstrap Processor (BSP), enables exception handling, and initializes all available Application Processors (APs). It also allows checking the total number of CPUs and retrieving CPU information. ```go package main import ( "runtime" "github.com/usbarmory/tamago/amd64" ) func main() { // Create AMD64 CPU instance (Bootstrap Processor) cpu := &amd64.CPU{ TimerMultiplier: 1, TimerOffset: 0, } // Initialize BSP (sets up LAPIC, features, timers) cpu.Init() // Enable exception handling cpu.EnableExceptions() // Initialize all available Application Processors // Pass -1 to initialize all APs, or a positive number to cap total cores cpu.InitSMP(-1) // Check number of CPUs after SMP initialization numCPU := cpu.NumCPU() println("Total CPUs:", numCPU) // Verify SMP via runtime println("GOMAXPROCS:", runtime.GOMAXPROCS(-1)) // Get processor identifier id := cpu.ID() println("Processor ID:", id) // Get CPU name name := cpu.Name() println("CPU:", name) // Reset CPU via keyboard controller cpu.Reset() } ``` -------------------------------- ### Launch QEMU for GDB Debugging Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/imx8mpevk/README.md This command launches QEMU with the necessary flags to enable GDB debugging. The `-S` flag tells QEMU to stop execution at the first instruction, and `-s` is a shortcut for `-gdb tcp::1234`, which opens a GDB server on port 1234. This allows GDB to connect and control the emulated target. ```shell qemu-system-aarch64 -M virt -cpu cortex-a53 -m 1024 -kernel main -display sdl -serial stdio -S -s ``` -------------------------------- ### Run Tamago with QEMU Source: https://github.com/usbarmory/tamago/blob/master/board/google/gcp/README.md Launches the Tamago paravirtualized target using QEMU. It configures the machine type, CPU features, memory, and network interfaces. The kernel 'main' is loaded directly. ```shell qemu-system-x86_64 \ -machine q35,pit=off,pic=off \ -enable-kvm -cpu host,invtsc=on,kvmclock=on -no-reboot \ -m 4G -nographic -monitor none -serial stdio \ -device pcie-root-port,port=0x10,chassis=1,id=pci.0,bus=pcie.0,multifunction=on,addr=0x3 \ -device virtio-net-device,netdev=net0,disable-modern=true -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ -kernel main ``` -------------------------------- ### Debug RISC-V QEMU Emulation with GDB Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/sifive_u/README.md This snippet demonstrates how to attach a GDB debugger to a running RISC-V QEMU emulation. It requires the QEMU emulator to be started with specific flags to enable GDB server functionality. The GDB client then connects to the emulator's listening port. ```sh riscv64-elf-gdb -ex "target remote 127.0.0.1:1234" main ``` -------------------------------- ### Manually Build TamaGo Distribution Source: https://github.com/usbarmory/tamago/blob/master/board/cloud_hypervisor/vm/README.md These commands demonstrate how to manually build the TamaGo Go distribution from source or use a pre-compiled binary release. This is an alternative to using the TamaGo CLI for managing the Go environment. ```sh wget https://github.com/usbarmory/tamago-go/archive/refs/tags/latest.zip unzip latest.zip cd tamago-go-latest/src && ./all.bash cd ../bin && export TAMAGO=`pwd`/go ``` -------------------------------- ### Execute Target in QEMU Emulation Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/mx6ullevk/README.md This command executes the target under QEMU emulation, specifying the machine type, CPU, memory, and network configuration. The '-kernel main' flag loads the kernel, and '-semihosting' enables semihosting operations. ```sh qemu-system-arm \ -machine mcimx6ul-evk -cpu cortex-a7 -m 512M \ -nographic -monitor none -serial null -serial stdio \ -net nic,model=imx.enet,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no \ -kernel main -semihosting ``` -------------------------------- ### Interface with VirtIO Devices in Go Source: https://context7.com/usbarmory/tamago/llms.txt This Go code provides an interface for interacting with VirtIO devices in virtualized environments. It covers device feature negotiation, initialization, retrieving device information, configuring virtual queues, and signaling readiness to the device. This is essential for virtual I/O operations. ```go package main import ( "github.com/usbarmory/tamago/kvm/virtio" ) func initVirtIODevice(dev virtio.VirtIO) error { // Get device features deviceFeatures := dev.DeviceFeatures() // Negotiate features (driver features AND device features) driverFeatures := deviceFeatures // Accept all // Initialize device with negotiated features err := dev.Init(driverFeatures) if err != nil { return err } // Get device ID deviceID := dev.DeviceID() println("Device ID:", deviceID) // Get negotiated features negotiated := dev.NegotiatedFeatures() println("Negotiated features:", negotiated) // Configure virtual queue queueIndex := 0 maxSize := dev.MaxQueueSize(queueIndex) dev.SetQueueSize(queueIndex, maxSize) // Create and register virtual queue queue := &virtio.VirtualQueue{} // ... configure queue ... dev.SetQueue(queueIndex, queue) // Signal ready dev.SetReady() // Notify device of available buffers dev.QueueNotify(queueIndex) return nil } ``` -------------------------------- ### Initialize ARM64 CPU (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Initializes the ARM64 core, supporting ARMv8-A Cortex-A53 cores for 64-bit ARM processors. This process involves setting up the vector table and the idle governor. It also includes functionality to wait for interrupts. ```go package main import ( "github.com/usbarmory/tamago/arm64" ) func main() { cpu := &arm64.CPU{ TimerMultiplier: 1, TimerOffset: 0, } // Initialize ARM64 core (sets up vector table, idle governor) cpu.Init() // Wait for interrupt cpu.WaitInterrupt() } ``` -------------------------------- ### Initialize RISC-V 64-bit CPU (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Initializes RISC-V 64-bit cores (RV64) in either machine or supervisor mode. It leverages the XLEN constant to indicate 64-bit support. This package is designed for bare metal execution on RISC-V 64-bit architectures. ```go package main import ( "github.com/usbarmory/tamago/riscv64" ) func main() { cpu := &riscv64.CPU{} // Initialize in machine mode cpu.Init() // Or initialize in supervisor mode cpu.InitSupervisor() // XLEN constant indicates 64-bit support println("XLEN:", riscv64.XLEN) } ``` -------------------------------- ### Importing Board Package in Go Application Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/microvm/README.md This Go code snippet shows how to import a specific board package, such as the QEMU microVM, into your application to ensure hardware initialization and runtime support. ```golang import ( _ "github.com/usbarmory/tamago/board/qemu/microvm" ) ``` -------------------------------- ### Compile Go Programs for Tamago (Shell) Source: https://github.com/usbarmory/tamago/blob/master/README.md This snippet demonstrates how to compile Go programs for the Tamago environment using the custom tamago build tool. It shows how to set the GOOSPKG environment variable and use the tamago compiler with specific linker flags for memory addresses. This is essential for building applications that run on bare metal or specific embedded environments. ```shell export GOOSPKG=github.com/usbarmory/tamago # Example for Cloud Hypervisory, QEMU and Firecracker KVMs GOOS=tamago GOARCH=amd64 ${TAMAGO} build -ldflags "-T 0x10010000 -R 0x1000" main.go ``` -------------------------------- ### Connect to QEMU GDB Server with GDB Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/imx8mpevk/README.md This command connects the ARM GDB client to the QEMU GDB server running on localhost at port 1234. The `-ex` flag allows executing a GDB command immediately after connection, in this case, setting the target remote. The `main` argument specifies the executable to load. ```shell arm-none-eabi-gdb -ex "target remote 127.0.0.1:1234" main ``` -------------------------------- ### SD/MMC Controller Initialization and Usage (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Initializes and uses the NXP uSDHC controller for SD cards and eMMC. Supports High Speed and DDR modes. Detects card type, retrieves information, and performs read/write operations. ```go package main import ( "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { // Initialize uSDHC controller with 4-bit bus width mmc := imx6ul.USDHC1 mmc.Init(4) // Detect and initialize card (auto-selects highest speed) err := mmc.Detect() if err != nil { panic(err) } // Get card information info := mmc.Info() println("MMC:", info.MMC) println("SD:", info.SD) println("High Capacity:", info.HC) println("High Speed:", info.HS) println("DDR:", info.DDR) println("Rate:", info.Rate, "bytes/sec") println("Block Size:", info.BlockSize) println("Blocks:", info.Blocks) // Read data from card data, err := mmc.Read(0, 512) // offset 0, 512 bytes if err != nil { panic(err) } // Read blocks (LBA-based) buf := make([]byte, 4096) err = mmc.ReadBlocks(0, buf) // Read 8 blocks starting at LBA 0 // Write blocks writeData := make([]byte, 512) copy(writeData, []byte("Data to write")) err = mmc.WriteBlocks(100, writeData) // Write to LBA 100 } ``` -------------------------------- ### Executing TamaGo Application with QEMU Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/sifive_u/README.md This command sequence demonstrates how to run a compiled TamaGo ELF image on the QEMU sifive_u emulator. It involves compiling a Device Tree Blob (DTB) and then launching QEMU with specific machine and emulation parameters. ```bash dtc -I dts -O dtb qemu-riscv64-sifive_u.dts -o qemu-riscv54-sifive_u.dtb qemu-system-riscv64 \ -machine sifive_u -m 512M \ -nographic -monitor none -serial stdio -net none \ -dtb qemu-riscv64-sifive_u.dtb \ -bios bios.bin ``` -------------------------------- ### Importing Board Package in Go Application Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/mx6ullevk/README.md This Go code snippet demonstrates how to import the necessary board package for the MCIMX6ULL-EVK. This ensures that hardware initialization and runtime support are correctly set up for the target platform. ```golang import ( _ "github.com/usbarmory/tamago/board/nxp/mx6ullevk" ) ``` -------------------------------- ### Compiling TamaGo Applications for QEMU sifive_u Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/sifive_u/README.md This command compiles a Go application for the QEMU sifive_u platform using the TamaGo distribution. It sets the necessary environment variables and build flags for bare metal execution. Ensure TAMAGO points to your TamaGo distribution's Go binary. ```bash GOOS=tamago GOOSPKG=github.com/usbarmory/tamago GOARCH=riscv64 \ ${TAMAGO} build -ldflags "-T 0x80010000 -R 0x1000" main.go ``` -------------------------------- ### Import Board Package for Hardware Initialization Source: https://github.com/usbarmory/tamago/blob/master/board/usbarmory/README.md This Go code demonstrates how to import a board-specific package, such as for the USB armory Mk II. Importing this package ensures that the necessary hardware initialization and runtime support are included in your bare metal application. ```go import ( _ "github.com/usbarmory/tamago/board/usbarmory/mk2" ) ``` -------------------------------- ### Using TamaGo Command-Line Tool Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/mx6ullevk/README.md This snippet shows how to use the `tamago` command-line tool to manage the TamaGo Go distribution. It can be used to run the `go` command directly or to integrate with the application's `go.mod` file. ```shell go run github.com/usbarmory/tamago/cmd/tamago ``` ```go.mod tool github.com/usbarmory/tamago/cmd/tamago ``` -------------------------------- ### Importing Board Package for Hardware Support Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/imx8mpevk/README.md This Go code snippet shows how to import the necessary board package for the 8MPLUSLPD4-EVK. Importing this package ensures that hardware initialization and runtime support are correctly set up for the target platform. ```go import ( _ "github.com/usbarmory/tamago/board/nxp/imx8mpevk" ) ``` -------------------------------- ### Build TamaGo Application for Linux Userspace Source: https://github.com/usbarmory/tamago/wiki/Home This command builds a TamaGo application for the Linux userspace. It requires the TAMAGO environment variable to be set, pointing to the TamaGo toolchain. The output is an executable file named 'main'. ```shell GOOS=tamago ${TAMAGO} build main.go ``` -------------------------------- ### Initialize ARM CPU and Manage Modes/Interrupts (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Initializes the ARM CPU instance, managing processor modes, exception handling, memory management, and interrupt control for ARMv7-A Cortex-A7 cores. It allows setting timer configurations, checking processor modes, enabling/disabling interrupts, and retrieving/setting system time. ```go package main import ( "github.com/usbarmory/tamago/arm" ) func main() { // Create ARM CPU instance with timer configuration cpu := &arm.CPU{ TimerMultiplier: 1, TimerOffset: 0, } // Initialize CPU with vector table base address (64KB reserved area) // This sets up exception handlers, MMU, and system timer cpu.Init(0x80000000) // Check current processor mode mode := cpu.Mode() modeName := arm.ModeName(mode) println("Current mode:", modeName) // Enable/disable interrupts cpu.EnableInterrupts(false) // Enable IRQ in current program status cpu.DisableInterrupts(false) // Disable IRQ in current program status // Wait for interrupt (low power idle) cpu.WaitInterrupt() // Get system time in nanoseconds ns := cpu.GetTime() println("System time:", ns) // Set system time cpu.SetTime(1000000000) // 1 second } ``` -------------------------------- ### DCP Cryptographic Accelerator Initialization (Go) Source: https://context7.com/usbarmory/tamago/llms.txt Initializes the NXP Data Co-Processor (DCP) for hardware-accelerated cryptography. Supports AES, SHA, CRC32, and key derivation. Available on i.MX6ULL/ULZ. ```go package main import ( "github.com/usbarmory/tamago/soc/nxp/imx6ul" ) func main() { // Initialize DCP (available on i.MX6ULL/ULZ) dcp := imx6ul.DCP dcp.Init() // Enable interrupt-based completion (optional) dcp.EnableInterrupt() // In interrupt handler: // dcp.ServiceInterrupt() // DCP supports: // - AES-128 encryption/decryption (CBC mode) // - SHA-1, SHA-256 hashing // - CRC32 // - Hardware key derivation } ``` -------------------------------- ### Convert Go ELF to Binary for Raspberry Pi Source: https://github.com/usbarmory/tamago/blob/master/board/raspberrypi/README.md This script uses objcopy and gcc from the GNU cross-compiler toolchain to convert a Go ELF binary into a format suitable for the Raspberry Pi firmware. It extracts specific sections, compiles a boot stub, and concatenates them into a single executable binary. Requires the CROSS_COMPILE environment variable to be set. ```sh $(CROSS_COMPILE)objcopy -j .text -j .rodata -j .shstrtab -j .typelink \ -j .itablink -j .gopclntab -j .go.buildinfo -j .go.module -j .noptrdata -j .data \ -j .bss --set-section-flags .bss=alloc,load,contents \ -j .noptrbss --set-section-flags .noptrbss=alloc,load,contents\ -O binary main main.o ${CROSS_COMPILE}gcc -D ENTRY_POINT=`${CROSS_COMPILE}readelf -e main | grep Entry | sed 's/.*\(0x[a-zA-Z0-9]*\).*/\1/'` -c boot.S -o boot.o ${CROSS_COMPILE}objcopy boot.o -O binary stub.o # Truncate pads the stub out to correctly align the binary # 32768 = 0x10000 (TEXT_START) - 0x8000 (Default kernel load address) truncate -s 32768 stub.o cat stub.o main.o > main.bin ``` -------------------------------- ### Executing QEMU MicroVM with TamaGo Source: https://github.com/usbarmory/tamago/blob/master/board/qemu/microvm/README.md This QEMU command launches a microVM instance configured for TamaGo applications. It specifies machine type, CPU features, memory, and serial console output. ```shell qemu-system-x86_64 \ -machine microvm,x-option-roms=on,pit=off,pic=off,rtc=on \ -global virtio-mmio.force-legacy=false \ -enable-kvm -cpu host,invtsc=on,kvmclock=on -no-reboot \ -m 4G -nographic -monitor none -serial stdio \ ``` -------------------------------- ### Import Board Package for Hardware Initialization Source: https://github.com/usbarmory/tamago/blob/master/board/cloud_hypervisor/vm/README.md This Go import statement is required in applications targeting specific hardware with TamaGo. It ensures that the necessary hardware initialization and runtime support for the chosen board (e.g., Cloud Hypervisor VM) are included in the build. ```go import ( _ "github.com/usbarmory/tamago/board/cloud_hypervisor/vm" ) ``` -------------------------------- ### Initialize GDB Debugging with openocd Source: https://github.com/usbarmory/tamago/blob/master/board/nxp/mx6ullevk/README.md This is a gdbinit file used for debugging with GDB over JTAG via openocd. It sets the remote target and configures hardware breakpoint and watchpoint limits. Ensure openocd version is greater than 0.11.0. ```gdb target remote localhost:3333 set remote hardware-breakpoint-limit 6 set remote hardware-watchpoint-limit 4 ```