├── arm_chainloader ├── drivers │ ├── cprman.cc │ ├── mbr_disk.h │ ├── fatfs │ │ ├── option │ │ │ └── unicode.c │ │ ├── 00readme.txt │ │ └── integer.h │ ├── mailbox.hpp │ ├── block_device.hpp │ └── mailbox.cc ├── lib_armv6 │ ├── arm_locore.s │ └── arm_strlen.s ├── shell.nix ├── chainloader.c ├── arm-defs.h ├── start.h ├── mmu.h ├── memory_map.h ├── linker.lds ├── chainloader.h └── trap.cc ├── .gitignore ├── firmware ├── shell.nix ├── sdram.h ├── arm_monitor.h ├── hang_cpu.c ├── romstage.h ├── interrupt.h ├── BCM2708PlatformStartup.h ├── lib │ └── stdarg.h ├── aux.h ├── startelf.h ├── vc4_include │ ├── vc4_types.h │ ├── cpu.h │ ├── pcb.h │ └── exception.h ├── drivers │ ├── gpclk.cc │ ├── gpclk.hh │ ├── BCM2708ArmControl.hh │ ├── BCM2708PowerManagement.hpp │ └── BCM2708ClockDomains.hpp ├── otp.h ├── startelf4.S ├── traps.h ├── utils.hh ├── linker.ld ├── panic.c ├── BCM2708PlatformStartup.cc ├── start.S ├── start.ld ├── aux.c ├── traps.S ├── trap.s ├── utils4.cc ├── otp_asm.s └── pll_read.c ├── notc ├── include │ ├── puts.h │ ├── fake-malloc.h │ └── xprintf.h ├── putchar.c ├── printf.c ├── Makefile └── puts.c ├── docs ├── screen-reader.txt ├── qpu-compute.txt ├── dt-blobs.txt ├── high-speed.txt ├── vec ├── cm4.txt ├── vpu_sandbox.txt ├── android-auto.txt ├── i2c-slave-boot.txt ├── bootflow.txt ├── rotary_encoder.txt ├── vchiq.txt ├── lan9512.txt ├── undocumented-security.txt ├── sdhost.txt ├── webusb.txt ├── suspend ├── boot.txt ├── rpi4-rom.txt ├── emmc2.txt ├── packages.txt ├── v4l.txt ├── pwm_audio.txt ├── hw-accel.txt ├── genet.txt ├── vpu-irq.txt ├── cpuid.txt ├── sd.txt ├── pcie.txt ├── stepping.txt ├── bluetooth.txt ├── cracking-rpi4-hmac.txt ├── xhci.txt ├── arm-jtag.txt ├── ddr4.txt ├── rpi1-jtag.txt ├── rpi4-dram.txt ├── rpi4-ethernet-phy.txt ├── hdmi.txt ├── bcm_xhci.txt ├── dsi.txt ├── v3d.txt ├── vpu-l1.txt ├── vpu-jtag.txt ├── devicetree.txt ├── pmic.txt ├── revision.txt ├── dwc2.txt ├── teletext.txt ├── csi.txt ├── i2c.txt ├── vcgencmd.txt ├── vce.txt ├── vcdbg.txt ├── rpi4-gpio-mux.dot ├── genet.md ├── isp.txt ├── start4.txt ├── vec.txt ├── arm-arch.txt ├── hyperpixel.txt ├── wifi.txt ├── vpu.txt ├── arm-mmu.txt ├── pixelvalve.md ├── jtag-raw.txt └── video-pipeline.md ├── dts ├── bcm283x-rpi-usb-host.dtsi ├── bcm283x-rpi-csi1-2lane.dtsi ├── bcm2836-rpi.dtsi ├── bcm283x-rpi-smsc9514.dtsi ├── bcm2835-common.dtsi ├── bcm2837-rpi-3-b.dts └── bcm2837.dtsi ├── hs-gpio ├── Setup.hs ├── cbits │ └── helper.c ├── Types.hs ├── hs-gpio.cabal ├── GPIO.hs ├── MainMenu.hs └── PromptString.hs ├── release.nix ├── common ├── broadcom │ └── bcm2708_chip │ │ ├── flow_config.tcl │ │ ├── h264.h │ │ ├── isp.h │ │ ├── nexus_uba.h │ │ ├── dpi.h │ │ ├── apb_arbiter_control.h │ │ ├── perfmon.h │ │ ├── README.txt │ │ ├── rnghw.h │ │ ├── rng.h │ │ ├── cdp.h │ │ ├── tectl_a0.h │ │ ├── timer.h │ │ ├── cryptohw.h │ │ ├── tectl.h │ │ └── ccp2tx_a0.h ├── include │ ├── hang_cpu.h │ ├── pl011.h │ ├── crc32.h │ ├── hexdump.h │ ├── pll_read.h │ ├── panic.h │ ├── runtime.h │ └── drivers │ │ ├── BCM2708Gpio.hpp │ │ └── IODevice.hpp ├── hardware.c ├── print_timestamp.c ├── default.nix ├── Makefile ├── crc32.c ├── put_dump.c ├── panic.c ├── udelay.c ├── IODevice.cc ├── hexdump.cc ├── eeprom.txt ├── BCM2708Gpio.cc ├── cxx_runtime.cc └── pl011.c ├── uart-manager └── Makefile ├── utils ├── map_peripherals.h ├── default.nix ├── Makefile ├── ramdumper.cc └── map_peripherals.cpp ├── gdb.txt ├── AUTHORS.md ├── nixos-with-fs.nix ├── install-openpi.sh ├── nixops.nix ├── board-details ├── rpi1-55a4377c.txt ├── rpi1-230aad04.txt ├── rpi2-1077df95.txt └── rpi3-9080d9b6.txt ├── tlsf ├── target.h ├── Makefile └── tlsf.h ├── arm64 ├── Makefile ├── stub.ld ├── start.s └── main.c ├── jtag ├── pi400-to-pi1.tcl ├── rpi4-to-rpi2.tcl └── rpi4-to-rpi3.tcl ├── rpi4-notes-v2.txt ├── CONTRIBUTING.md ├── style.sh ├── sign.js ├── bootloader.nix ├── systemd.patch ├── bcm2835.nix ├── notes.txt ├── tools └── wslstage.py ├── my-init.c ├── official-boot-flow.dot ├── netboot.nix ├── nix └── sources.json └── nixos.nix /arm_chainloader/drivers/cprman.cc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.o 3 | *.d 4 | -------------------------------------------------------------------------------- /firmware/shell.nix: -------------------------------------------------------------------------------- 1 | (import ../. {}).vc4.firmware 2 | -------------------------------------------------------------------------------- /notc/include/puts.h: -------------------------------------------------------------------------------- 1 | int __puts(const char *s); 2 | -------------------------------------------------------------------------------- /arm_chainloader/lib_armv6/arm_locore.s: -------------------------------------------------------------------------------- 1 | .text 2 | .align 2 3 | -------------------------------------------------------------------------------- /arm_chainloader/shell.nix: -------------------------------------------------------------------------------- 1 | (import ../. {}).arm.chainloader 2 | -------------------------------------------------------------------------------- /firmware/sdram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void sdram_init(void); 4 | -------------------------------------------------------------------------------- /docs/screen-reader.txt: -------------------------------------------------------------------------------- 1 | terminal, in-kernel, speakup 2 | gui, orca 3 | -------------------------------------------------------------------------------- /dts/bcm283x-rpi-usb-host.dtsi: -------------------------------------------------------------------------------- 1 | &usb { 2 | dr_mode = "host"; 3 | }; 4 | -------------------------------------------------------------------------------- /hs-gpio/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /release.nix: -------------------------------------------------------------------------------- 1 | builtins.removeAttrs (import ./. {}) [ "aarch64-shell" ] 2 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/flow_config.tcl: -------------------------------------------------------------------------------- 1 | enable_flow create_regs 2 | 3 | -------------------------------------------------------------------------------- /docs/qpu-compute.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=31&t=278081 2 | -------------------------------------------------------------------------------- /common/include/hang_cpu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void __attribute__((noreturn)) hang_cpu(void); 4 | -------------------------------------------------------------------------------- /common/include/pl011.h: -------------------------------------------------------------------------------- 1 | void pl011_uart_init(uint32_t baud); 2 | void pl011_putchar(unsigned char c); 3 | -------------------------------------------------------------------------------- /docs/dt-blobs.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=107&t=281856 2 | custom plld freq 3 | -------------------------------------------------------------------------------- /docs/high-speed.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1286497#p1286497 2 | smi/dsi/csi 3 | -------------------------------------------------------------------------------- /firmware/arm_monitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void arm_monitor_interrupt(void); 4 | void monitor_start(void); 5 | -------------------------------------------------------------------------------- /common/include/crc32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | extern "C" uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len); 3 | -------------------------------------------------------------------------------- /docs/vec: -------------------------------------------------------------------------------- 1 | (composite video output) 2 | 3 | base clock is 108mhz, muxed from pllh on the rpi3, pllc on the rpi4 4 | -------------------------------------------------------------------------------- /docs/cm4.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=293966 2 | 3 | emmc is locked at 1.8v and cant cut power 4 | -------------------------------------------------------------------------------- /docs/vpu_sandbox.txt: -------------------------------------------------------------------------------- 1 | setting a region: 2 | L1_L1_SANDBOX_STARTn = 7 3 | L1_L1_SANDBOX_ENDn = $end 4 | L1_L1_SANDBOX_STARTn = $start 5 | -------------------------------------------------------------------------------- /firmware/hang_cpu.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cpu.h" 3 | 4 | void __attribute__((noreturn)) hang_cpu() { 5 | _hang_cpu(); 6 | } 7 | -------------------------------------------------------------------------------- /docs/android-auto.txt: -------------------------------------------------------------------------------- 1 | https://github.com/viktorgino/headunit-desktop 2 | https://github.com/viktorgino/libheadunit 3 | https://github.com/f1xpl/openauto 4 | -------------------------------------------------------------------------------- /arm_chainloader/chainloader.c: -------------------------------------------------------------------------------- 1 | #include "chainloader.h" 2 | #include 3 | 4 | void __attribute__((noreturn)) hang_cpu() { 5 | _hang_cpu(); 6 | } 7 | -------------------------------------------------------------------------------- /dts/bcm283x-rpi-csi1-2lane.dtsi: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0-only 2 | &csi1 { 3 | port { 4 | endpoint { 5 | data-lanes = <1 2>; 6 | }; 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /uart-manager/Makefile: -------------------------------------------------------------------------------- 1 | LDFLAGS += -lpthread 2 | 3 | uart-manager: uart-manager.cpp 4 | 5 | install: uart-manager 6 | mkdir -pv $(out)/bin 7 | cp uart-manager $(out)/bin/ 8 | -------------------------------------------------------------------------------- /dts/bcm2836-rpi.dtsi: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | #include "bcm2835-rpi.dtsi" 3 | 4 | &vchiq { 5 | compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq"; 6 | }; 7 | -------------------------------------------------------------------------------- /firmware/romstage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pcb.h" 4 | 5 | extern uint32_t g_CPUID; 6 | 7 | int _main(unsigned int cpuid, uint32_t load_address, vc4_saved_state_t* pcb); 8 | -------------------------------------------------------------------------------- /docs/i2c-slave-boot.txt: -------------------------------------------------------------------------------- 1 | OTP17 bit 27 will enable i2c-slave boot support 2 | when enabled, gpio 18/19 are set to ALT3 mode, and the SoC will act as an i2c slave on address 0x66 3 | 4 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/mbr_disk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef __cplusplus 3 | extern "C" { 4 | #endif 5 | 6 | void init_mbr_disk(); 7 | 8 | #ifdef __cplusplus 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /docs/bootflow.txt: -------------------------------------------------------------------------------- 1 | stage 0, the boot rom in the SoC 2 | stage 1, bootcode.bin, brings dram online 3 | stage 2, start(4).elf, the rest of the firmware 4 | state 3, kernel.img, the arm kernel 5 | -------------------------------------------------------------------------------- /docs/rotary_encoder.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1754475#p1754475 2 | 3 | > multiple rotary_encoder dtoverlays 4 | > dtoverlay=rotary-encoder,pin_a=12,pin_b=13 5 | 6 | -------------------------------------------------------------------------------- /common/hardware.c: -------------------------------------------------------------------------------- 1 | #include "hardware.h" 2 | 3 | const char* size_to_string[] = { 4 | "1GB", 5 | "512MB", 6 | "256MB", 7 | "128MB", 8 | "2GB", 9 | "4GB", 10 | "UNKNOWN" 11 | }; 12 | -------------------------------------------------------------------------------- /firmware/interrupt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void set_interrupt(int intno, bool enable, int core); 4 | void setup_irq_handlers(void); 5 | typedef void (*irqType)(); 6 | 7 | extern irqType vectorTable[]; 8 | -------------------------------------------------------------------------------- /docs/vchiq.txt: -------------------------------------------------------------------------------- 1 | https://github.com/RusPiRo/ruspiro-vchiq 2 | https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=296492&p=1787208#p1787208 3 | https://picamera.readthedocs.io/en/latest/fov.html#division-of-labor 4 | -------------------------------------------------------------------------------- /docs/lan9512.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=72070 2 | https://www.raspberrypi.org/forums/viewtopic.php?f=31&t=12530&start=25 3 | 4 | allows direct control of the LED's on the ethernet port 5 | -------------------------------------------------------------------------------- /firmware/BCM2708PlatformStartup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "otp.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | void PEStartPlatform(struct OtpInfo *info); 9 | #ifdef __cplusplus 10 | }; 11 | #endif 12 | -------------------------------------------------------------------------------- /common/print_timestamp.c: -------------------------------------------------------------------------------- 1 | #include "hardware.h" 2 | 3 | #include 4 | 5 | void print_timestamp() { 6 | uint32_t clock_lo = ST_CLO; 7 | 8 | printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); 9 | } 10 | -------------------------------------------------------------------------------- /utils/map_peripherals.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct peripherals { 4 | int fd; 5 | void *peripherals_start; 6 | unsigned int physical_start; 7 | int vc; 8 | }; 9 | 10 | void open_peripherals(struct peripherals &handle); 11 | -------------------------------------------------------------------------------- /firmware/lib/stdarg.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma once 4 | 5 | typedef __builtin_va_list va_list; 6 | 7 | #define va_start(v,l) __builtin_va_start(v,l) 8 | #define va_arg(v,l) __builtin_va_arg(v,l) 9 | #define va_end(v) __builtin_va_end(v) -------------------------------------------------------------------------------- /gdb.txt: -------------------------------------------------------------------------------- 1 | set style enabled off 2 | target remote :3333 3 | set disassemble-next-line on 4 | 5 | define doit 6 | shell nix-build .. -A aarch64.chainloader64 --option substituters '' --option builders '' 7 | load result/arm64.elf 8 | file result/arm64.elf 9 | -------------------------------------------------------------------------------- /docs/undocumented-security.txt: -------------------------------------------------------------------------------- 1 | the maskrom at 0x6000_0000 appears to vanish from the bus once linux is running 2 | the HVS is read-only from the arm until the firmware unlocks it 3 | the DDR2 control registers return 0 when read from the arm, even under closed firmware 4 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Authors of the `rpi-open-firmware` project are listed below, for purposes of determing copyright. Please keep sorted. 2 | 3 | --- 4 | 5 | * Alex Badea 6 | * Alyssa Rosenzweig 7 | * Kristina Brooks 8 | -------------------------------------------------------------------------------- /notc/putchar.c: -------------------------------------------------------------------------------- 1 | #include "xprintf.h" 2 | 3 | /*----------------------------------------------*/ 4 | /* Put a character */ 5 | /*----------------------------------------------*/ 6 | 7 | int putchar (int c) { 8 | pl011_putchar(c); 9 | } 10 | -------------------------------------------------------------------------------- /firmware/aux.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct uart_device { 4 | volatile uint32_t *data_reg; 5 | volatile uint32_t *lsr_reg; 6 | }; 7 | 8 | extern struct uart_device aux_uart; 9 | extern FILE *aux_fd; 10 | 11 | void setup_aux_uart(uint32_t baud); 12 | void aux_flush(); 13 | -------------------------------------------------------------------------------- /common/include/hexdump.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void hexdump_ram(volatile void *realaddr, uint32_t reportaddr, uint32_t count); 8 | void safe_putchar(unsigned char c); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /docs/sdhost.txt: -------------------------------------------------------------------------------- 1 | https://gist.github.com/eggman/40612fdeb6d081a9a7d1a63ddef647f1 2 | https://patchwork.kernel.org/patch/9192525/ 3 | u-boot/drivers/mmc/bcm2835_sdhost.c 4 | 5 | SDHOST is at 0x7e202000, appears to be a broadcom custom controller, and has "better performance" compared to SDHCI 6 | -------------------------------------------------------------------------------- /docs/webusb.txt: -------------------------------------------------------------------------------- 1 | 2020-11-22 23:32:53 < clever> ali1234: there is also, chrome://usb-internals/ and chrome://device-log/?refresh=30 2 | 2020-11-22 23:35:39 < ali1234> so to make it work you just need to make sure usbmon is not loaded, and run "sudo snap connect chromium:raw-usb" if using the snap 3 | 4 | -------------------------------------------------------------------------------- /firmware/startelf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void main_entry(vc4_saved_state_t* pcb); 4 | void do_arm_dump(void); 5 | void gpclk0_test(void); 6 | void spin_the_gpio_wheel(void); 7 | void poke_the_dog(void); 8 | void fill_range_numbered(uint32_t addr, uint32_t count); 9 | void test_caches(void); 10 | -------------------------------------------------------------------------------- /arm_chainloader/arm-defs.h: -------------------------------------------------------------------------------- 1 | #define ARM32_MODE_MASK 0x1f 2 | #define ARM32_USR 0x10 3 | #define ARM32_FIQ 0x11 4 | #define ARM32_IRQ 0x12 5 | #define ARM32_SVC 0x13 6 | #define ARM32_MON 0x16 7 | #define ARM32_ABT 0x17 8 | #define ARM32_HYP 0x1a 9 | #define ARM32_UND 0x1b 10 | #define ARM32_SYS 0x1f 11 | -------------------------------------------------------------------------------- /notc/include/fake-malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef HAS_DYNAMIC_ALLOCATIONS 2 | static inline void* malloc(size_t size) { panic("malloc: dynamic allocations not supported on this configuration"); } 3 | static inline void free(void* obj) { panic("free: dynamic allocations not supported on this configuration"); } 4 | #endif 5 | -------------------------------------------------------------------------------- /docs/suspend: -------------------------------------------------------------------------------- 1 | https://wiki.ubuntu.com/DebuggingKernelSuspend 2 | https://wiki.ubuntu.com/DebuggingKernelHibernate 3 | https://www.kernel.org/doc/html/latest/power/swsusp.html 4 | https://www.kernel.org/doc/html/latest/power/userland-swsusp.html 5 | https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html 6 | 7 | -------------------------------------------------------------------------------- /nixos-with-fs.nix: -------------------------------------------------------------------------------- 1 | { 2 | imports = [ ./nixos.nix ]; 3 | fileSystems = { 4 | "/" = { 5 | device = "/dev/mmcblk0p2"; 6 | fsType = "ext4"; 7 | }; 8 | "/boot" = { 9 | device = "/dev/mmcblk0p1"; 10 | fsType = "vfat"; 11 | options = [ "nofail" ]; 12 | }; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /docs/boot.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=279585 2 | > start.elf and more importantly the ROM (for recovery.bin) require the boot partition to be in one of the first 8 FAT/EFI partitions (skipping over unrecognised partition types).Similarly, make sure the boot partition is within the first 2TB 3 | 4 | -------------------------------------------------------------------------------- /notc/printf.c: -------------------------------------------------------------------------------- 1 | #include "xprintf.h" 2 | 3 | int printf ( /* Put a formatted string to the default device */ 4 | const char* fmt, /* Pointer to the format string */ 5 | ... /* Optional arguments */ 6 | ) 7 | { 8 | va_list arp; 9 | 10 | va_start(arp, fmt); 11 | vprintf(fmt, arp); 12 | va_end(arp); 13 | } 14 | -------------------------------------------------------------------------------- /docs/rpi4-rom.txt: -------------------------------------------------------------------------------- 1 | reading over it, it will detect the following MBR type codes 2 | 0x83 (linux stuff, completely ignored) 3 | 0xee (gpt protective mbr) 4 | 0x01, 0x04, 0x06, 0x0b, 0x0c, 0x0e (all the fats) 5 | 0x07 (ntfs or exfat) has a special branch in the code 6 | if it encounters any other type, i think it stops iterating over partitions 7 | -------------------------------------------------------------------------------- /firmware/vc4_include/vc4_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef unsigned long long u64; 6 | typedef unsigned int u32; 7 | typedef unsigned short u16; 8 | typedef unsigned char u8; 9 | 10 | #define ALWAYS_INLINE __attribute__((always_inline)) inline 11 | 12 | #define _OPEN_SOURCE 13 | 14 | -------------------------------------------------------------------------------- /utils/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, common, raspberrypi-tools, libdrm, pkgconfig }: 2 | 3 | stdenv.mkDerivation { 4 | name = "utils"; 5 | nativeBuildInputs = [ pkgconfig ]; 6 | buildInputs = [ common raspberrypi-tools libdrm ]; 7 | src = stdenv.lib.cleanSource ./.; 8 | dontStrip = true; 9 | enableParallelBuilding = true; 10 | } 11 | -------------------------------------------------------------------------------- /arm_chainloader/start.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void asm_drop_secure(); 8 | void asm_enable_fpu(); 9 | void asm_set_ACTLR(uint32_t); 10 | void set_CPUECTLR(); 11 | void enable_icache(); 12 | void disable_icache(); 13 | void debug_stall(); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /docs/emmc2.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1883142#p1883142 2 | > I think the problem is that the CM4, like newer Pi 4s, has a BCM2711C0. They differ in that the EMMC2 interface is on the ARM (not VPU) memory bus, so the (dma-)ranges property is different. The firmware takes care of the changes, but by bypassing it you miss out. 3 | 4 | -------------------------------------------------------------------------------- /dts/bcm283x-rpi-smsc9514.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | aliases { 3 | ethernet0 = ðernet; 4 | }; 5 | }; 6 | 7 | &usb { 8 | usb1@1 { 9 | compatible = "usb424,9514"; 10 | reg = <1>; 11 | #address-cells = <1>; 12 | #size-cells = <0>; 13 | 14 | ethernet: usbether@1 { 15 | compatible = "usb424,ec00"; 16 | reg = <1>; 17 | }; 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /install-openpi.sh: -------------------------------------------------------------------------------- 1 | #! @crossShell@ 2 | # meant to be used as part of nixos, not ran manually 3 | 4 | ln -svf $1/init /init 5 | 6 | for file in bootcode.bin rpi2.dtb rpi3.dtb; do 7 | cp -v @bootdir@/$file /boot/ 8 | done 9 | 10 | cp -vL $1/initrd /boot/initrd 11 | 12 | echo "systemConfig=$1 init=$1/init $(cat $1/kernel-params)" > /boot/cmdline.txt 13 | -------------------------------------------------------------------------------- /nixops.nix: -------------------------------------------------------------------------------- 1 | # from `niv show nixpkgs` 2 | # nixops modify -d rpi nixops.nix -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/45e01e508a792077c77067467e07bce757932fb6.tar.gz 3 | { 4 | network.enableRollback = true; 5 | rpi = { 6 | imports = [ 7 | ./nixos-with-fs.nix 8 | ]; 9 | deployment.targetHost = "192.168.2.177"; 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /board-details/rpi1-55a4377c.txt: -------------------------------------------------------------------------------- 1 | OTP17: 0x1020000a 2 | 19.2mhz crystal present 3 | SDIO pullups should be on? 4 | SD card boot enabled 5 | USB device boot enabled 6 | 7 | SoC serial# 0x55a4377c 8 | 9 | HW revision: 0x00000002 10 | 11 | Optional Mac Override: 000000000 12 | 13 | OTP66: 0x00000000 14 | 15 | 16 | original rpi 1 b, 256mb ram, egoman 17 | -------------------------------------------------------------------------------- /arm_chainloader/mmu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef struct level1_entry_t { 10 | uint32_t addr : 20; 11 | } level1_entry; 12 | 13 | void init_page_tables(uint32_t ram_size); 14 | void mmu_off(void); 15 | void print_cache_tree(void); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /docs/packages.txt: -------------------------------------------------------------------------------- 1 | https://raspberrypi.stackexchange.com/questions/840/why-is-the-cpu-sometimes-referred-to-as-bcm2708-sometimes-bcm2835 2 | 3 | BCM2708 is the raw silicon you can find inside a pi0/pi1/roku2 4 | BCM2763 is that silicon, wire-bonded to 256mb of dram, all in one package 5 | BCM2835 is that same silicon, in its own double-sided package, for use in package-on-package configurations 6 | -------------------------------------------------------------------------------- /tlsf/target.h: -------------------------------------------------------------------------------- 1 | #ifndef _TARGET_H_ 2 | #define _TARGET_H_ 3 | 4 | #include 5 | 6 | #define TLSF_MLOCK_T pthread_mutex_t 7 | #define TLSF_CREATE_LOCK(l) pthread_mutex_init (l, NULL) 8 | #define TLSF_DESTROY_LOCK(l) pthread_mutex_destroy(l) 9 | #define TLSF_ACQUIRE_LOCK(l) pthread_mutex_lock(l) 10 | #define TLSF_RELEASE_LOCK(l) pthread_mutex_unlock(l) 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /firmware/drivers/gpclk.cc: -------------------------------------------------------------------------------- 1 | #include "drivers/gpclk.hh" 2 | 3 | GPCLK GPCLK0 = GPCLK(&CM_GP0CTL, &CM_GP0DIV, "GPCLK0"); 4 | GPCLK GPCLK1 = GPCLK(&CM_GP1CTL, &CM_GP1DIV, "GPCLK1"); 5 | GPCLK GPCLK2 = GPCLK(&CM_GP2CTL, &CM_GP2DIV, "GPCLK2"); 6 | 7 | GPCLK::GPCLK(volatile uint32_t *ctrl_addr, volatile uint32_t *div_addr, const char *name) { 8 | ctrl = ctrl_addr; 9 | divider = div_addr; 10 | setName(name); 11 | } 12 | -------------------------------------------------------------------------------- /docs/v4l.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=294684 2 | 3 | > Each time you open the Memory to Memory (M2M) devices you get a totally new standalone instance of the decoder/encoder/simple isp (not for the complex ISP on /dev/video13-16). 4 | > v4l2-ctl will therefore only tell you the default values, or the values that you've set in that particular v4l2-ctl call, as it closes the file handle at the end. 5 | 6 | -------------------------------------------------------------------------------- /arm64/Makefile: -------------------------------------------------------------------------------- 1 | all: arm64.elf arm64.bin 2 | 3 | CFLAGS = -nostdlib -nostartfiles -ffreestanding -g 4 | 5 | arm64.elf: start.o main.o 6 | $(LD) $^ -o $@ -Map=arm64.map -g -T stub.ld -lcommon -N -lnotc -nostdlib 7 | 8 | arm64.bin: arm64.elf 9 | $(OBJCOPY) -O binary $< $@ 10 | 11 | arm64.S: arm64.elf 12 | $(OBJDUMP) -d $< > $@ 13 | 14 | install: arm64.elf arm64.bin arm64.map arm64.S 15 | mkdir -pv ${out} 16 | cp -vi $^ ${out} 17 | -------------------------------------------------------------------------------- /docs/pwm_audio.txt: -------------------------------------------------------------------------------- 1 | > From a software perspective you just need to add "dtoverlay=audremap" to config.txt, which will enable the audio outputs on GPIOs 12 & 13 (header pins 32 and 33). "dtoverlay=audremap,pins_18_19" will send the output to GPIOs 18 & 19 (header pins 12 & 35) . But as James says, you really need some external circuitry to turn it into a usable audio signal. 2 | 3 | https://www.raspberrypi.org/forums/viewtopic.php?p=1754646#p1754646 4 | -------------------------------------------------------------------------------- /docs/hw-accel.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=294033 2 | /dev/video names 3 | 4 | 0 is the Unicam image node 5 | 1 is the Unicam metadata node (not actually relevant here) 6 | 10 is the video decoder 7 | 11 is the video encoder 8 | 12 is the simple video conversion/resize using the ISP 9 | 13-16 are the more complex ISP. 10 | 13 is the input 11 | 14 hi res output 12 | 15 low res output 13 | 16 stats output. 14 | 15 | -------------------------------------------------------------------------------- /hs-gpio/cbits/helper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *c_mmap_helper(uint32_t offset, uint32_t size, int fd) { 7 | void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); 8 | //printf("%p %d\n", addr, errno); 9 | //uint32_t *addr2 = addr; 10 | //for (int i=0; i<64; i++) { 11 | // printf("%d %x\n", i, addr2[i]); 12 | //} 13 | return addr; 14 | } 15 | -------------------------------------------------------------------------------- /jtag/pi400-to-pi1.tcl: -------------------------------------------------------------------------------- 1 | adapter driver sysfsgpio 2 | sysfsgpio_jtag_nums 11 25 10 9 3 | sysfsgpio_trst_num 7 4 | 5 | set _CHIPNAME rpi1 6 | 7 | transport select jtag 8 | 9 | set _DAP_TAPID 0x07b7617F 10 | 11 | jtag newtap $_CHIPNAME arm -irlen 5 -expected-id $_DAP_TAPID 12 | 13 | set _TARGETNAME $_CHIPNAME.arm1176 14 | 15 | target create $_TARGETNAME arm11 -chain-position $_CHIPNAME.arm 16 | 17 | rpi1.arm1176 configure -event gdb-attach { halt } 18 | 19 | -------------------------------------------------------------------------------- /rpi4-notes-v2.txt: -------------------------------------------------------------------------------- 1 | so, I can talk to the MxL7004 now 2 | that was an easy one - the I2C bus frequency must run at a much lower speed 3 | but the firmware sucks again; they're writing magic values to undocumented registers, XORing values read from other registers and comparing them to XORed values of other (documented) registers 4 | why on Earth? 5 | and then there's an undocumented register 0xf that can be read only immediately after you read BUCK4 voltage 4 times in a row 6 | -------------------------------------------------------------------------------- /firmware/otp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct OtpInfo { 6 | int type; 7 | int rev; 8 | int proc; 9 | uint32_t serial; 10 | uint32_t revision; 11 | }; 12 | 13 | void dump_otp(void); 14 | void otp_open(void); 15 | void otp_close(void); 16 | uint32_t otp_read_reg(uint32_t addr); 17 | 18 | uint32_t otp_read(uint8_t addr); 19 | void dump_all_otp(void); 20 | void pretty_print_otp(void); 21 | 22 | void parse_otp_into(struct OtpInfo *dest); 23 | -------------------------------------------------------------------------------- /docs/genet.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=252049 2 | 3 | controlling genet activity LED's 4 | 5 | 6 | genet tx cheap, irq/cpu wise 7 | genet rx is expensive 8 | 9 | when iperf is bound to core0 (same as irq), and doing gigabit rx, there is nearly 1 genet A irq for every packet received, 89k irq/sec, irq B is nearly idle, 938 Mbits/sec 10 | if iperf is bound to core1, genet A drops to 68k/sec, and B rises to 19.5k/sec, 941 Mbits/sec 11 | 12 | 13 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/h264.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define H264_BASE 0x7f000000 3 | #define H264_APB_ID 0x68323634 4 | #define H264_RC HW_REGISTER_RW( 0x7f000000 ) 5 | #define H264_RC_MASK 0xffffffff 6 | #define H264_RC_WIDTH 32 7 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/isp.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define ISP_BASE 0x7ea00000 3 | #define ISP_APB_ID 0x20697370 4 | #define ISP_RC HW_REGISTER_RW( 0x7ea00000 ) 5 | #define ISP_RC_MASK 0xffffffff 6 | #define ISP_RC_WIDTH 32 7 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/nexus_uba.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define NU_BASE 0x7e008000 3 | #define NU_HOSTIO_OF HW_REGISTER_RW( 0x7e008000 ) 4 | #define NU_HOSTIO_OF_MASK 0xffffffff 5 | #define NU_HOSTIO_OF_WIDTH 32 6 | #define NU_HOSTIO_OF_RESET 0000000000 7 | -------------------------------------------------------------------------------- /firmware/drivers/gpclk.hh: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum MashControl { 4 | kMashControlNone = 0, 5 | kMashControl1 = 1, 6 | kMashControl2 = 2, 7 | kMashControl3 = 3 8 | }; 9 | 10 | struct GPCLK : IODevice { 11 | GPCLK(volatile uint32_t *ctrl_addr, volatile uint32_t *div_addr, const char *name); 12 | private: 13 | volatile uint32_t *ctrl; 14 | volatile uint32_t *divider; 15 | }; 16 | 17 | extern GPCLK GPCLK0; 18 | extern GPCLK GPCLK1; 19 | extern GPCLK GPCLK2; 20 | -------------------------------------------------------------------------------- /arm64/stub.ld: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | MEMORY { 4 | ram (rwx) : ORIGIN = 0, LENGTH = 1M 5 | } 6 | SECTIONS { 7 | .text : { 8 | *(.text.start) 9 | *(.text) 10 | *(.text.*) 11 | } >ram 12 | 13 | .rodata : { 14 | *(.todata) 15 | } >ram 16 | 17 | .data : { 18 | *(.data) 19 | } >ram 20 | 21 | .bss : { 22 | *(.bss) 23 | } >ram 24 | 25 | /* First location in stack is highest address in RAM */ 26 | PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 16); 27 | } 28 | -------------------------------------------------------------------------------- /tlsf/Makefile: -------------------------------------------------------------------------------- 1 | all: libtlsf.a 2 | 3 | CFLAGS=-ffunction-sections -fdata-sections 4 | 5 | ifeq (${CC},vc4-elf-gcc) 6 | CFLAGS= 7 | else 8 | ifeq (${CC},aarch64-unknown-linux-gnu-gcc) 9 | CFLAGS += 10 | else 11 | CFLAGS += -mtune=arm1176jzf-s -march=armv6zk -mfpu=vfp -mfloat-abi=softfp 12 | endif 13 | endif 14 | 15 | libtlsf.a: tlsf.o 16 | ${AR} rcs $@ $^ 17 | 18 | install: libtlsf.a 19 | mkdir -p ${out}/{lib,include/tlsf} 20 | cp tlsf.h ${out}/include/tlsf 21 | cp libtlsf.a ${out}/lib 22 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/fatfs/option/unicode.c: -------------------------------------------------------------------------------- 1 | #include "../ff.h" 2 | 3 | #if _USE_LFN != 0 4 | 5 | #if _CODE_PAGE == 932 /* Japanese Shift_JIS */ 6 | #include "cc932.c" 7 | #elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ 8 | #include "cc936.c" 9 | #elif _CODE_PAGE == 949 /* Korean */ 10 | #include "cc949.c" 11 | #elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ 12 | #include "cc950.c" 13 | #else /* Single Byte Character-Set */ 14 | #include "ccsbcs.c" 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | So you'd like to contribute to `rpi-open-firmware`? 2 | 3 | First things first, please come on IRC before starting anything. While not strictly a rule, this prevents duplicate work. When you are ready after that, we accept pull requests over Github, or if you prefer you can email a patch or link to one over IRC. 4 | 5 | A few notes on style: 6 | 7 | * Contributors should use hard tabs. 8 | * C++ is the preferred language for high-level code. 9 | * Generally follow conventions of similar code in the project. 10 | -------------------------------------------------------------------------------- /docs/vpu-irq.txt: -------------------------------------------------------------------------------- 1 | MMIOBASE + 0x2000 == IC0 2 | MMIOBASE + 0x2800 == IC1 3 | 4 | ICn + 0x10 is the irq masking registers 5 | each register is 32bits wide, and references 8 irq 6 | ICn+0x10 is for irq 0-7 7 | ICn+0x14 is for irq 8-15 8 | ICn+0x18 is for irq 9-23 9 | ICn+0x1c is for irq 24-31 10 | ICn+0x20 is for irq 32-39 11 | ICn+0x24 is for irq 40-47 12 | ICn+0x28 is for irq 48-55 13 | ICn+0x2c is for irq 56-63 14 | 15 | for each register, it contains an array of 8 x 4bit fields 16 | setting all 4 bits to 0xF will enable an irq 17 | -------------------------------------------------------------------------------- /board-details/rpi1-230aad04.txt: -------------------------------------------------------------------------------- 1 | OTP17: 0x1020000a 2 | 19.2mhz crystal present 3 | SDIO pullups should be on? 4 | SD card boot enabled 5 | USB device boot enabled 6 | 7 | SoC serial# 0x230aad04 8 | 9 | HW revision: 0x0000000e 10 | 11 | Optional Mac Override: 000000000 12 | 13 | OTP66: 0x00000000 14 | 15 | 16 | rpi 1 b, rev 2, 512mb, sony uk 17 | 18 | 19 | MIDR: 0x410fb767 20 | armv6 cache type: 0x1d152152 21 | L1i: words: 2, assoc: 2, size: 5, size2: 0 22 | L1d: words: 2, assoc: 2, size: 5, size2: 0 23 | S: 1 24 | CType: 14 25 | -------------------------------------------------------------------------------- /style.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # runs astyle on our code to conform to project standards 4 | # contributors should run this prior to PRs 5 | 6 | # a handful of subprojects (BCM headers, libfdt, etc.) are included in-tree 7 | # to avoid create merge conflicts when pulling upstream, only style our code 8 | FILES="*.c *.cc *.h arm_chainloader/*.c arm_chainloader/*.cc arm_chainloader/*.h arm_chainloader/drivers/*.cc arm_chainloader/drivers/*.hpp" 9 | 10 | # run astyle with tabs and attached braces 11 | astyle --style=attach --indent=tab $FILES 12 | -------------------------------------------------------------------------------- /firmware/startelf4.S: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | mov sp, _fstack 4 | di 5 | #if 0 6 | stm r0, (--sp) // dummy 7 | stm r0, (--sp) // values 8 | stm lr, (--sp) 9 | stm r0-r5, (--sp) 10 | stm r6-r15, (--sp) 11 | stm r16-r23, (--sp) 12 | mov r0, sp 13 | #else 14 | mov r0, 0 15 | #endif 16 | bl main_entry 17 | loop: 18 | b loop 19 | 20 | .global gpio_test 21 | gpio_test: 22 | nop 23 | mov r2, 0x7e003004 24 | gpio_loop: 25 | ld r3, (r2) 26 | st r3, (r1) 27 | add r1, 0x4 28 | addcmpbne r0, -1, 0x0, gpio_loop 29 | rts 30 | -------------------------------------------------------------------------------- /notc/Makefile: -------------------------------------------------------------------------------- 1 | all: libnotc.a 2 | 3 | BASECFLAGS=-Iinclude -g 4 | ARMCFLAGS=-mtune=arm1176jzf-s -march=armv6zk -mfpu=vfp -mfloat-abi=softfp #-mthumb 5 | ifeq (${CC},vc4-elf-gcc) 6 | CFLAGS=${BASECFLAGS} 7 | else 8 | ifeq (${CC},aarch64-unknown-linux-gnu-gcc) 9 | CFLAGS=${BASECFLAGS} 10 | else 11 | CFLAGS=${BASECFLAGS} ${ARMCFLAGS} 12 | endif 13 | endif 14 | 15 | libnotc.a: xprintf.o puts.o putchar.o printf.o 16 | ${AR} rcs $@ $^ 17 | 18 | install: libnotc.a 19 | mkdir -pv ${out}/lib 20 | cp libnotc.a ${out}/lib 21 | cp -r include ${out} 22 | -------------------------------------------------------------------------------- /notc/puts.c: -------------------------------------------------------------------------------- 1 | #include "xprintf.h" 2 | 3 | /*----------------------------------------------*/ 4 | /* Put a null-terminated string */ 5 | /*----------------------------------------------*/ 6 | 7 | int __puts ( /* Put a string to the default device */ 8 | const char* str /* Pointer to the string */ 9 | ) 10 | { 11 | while (*str) 12 | putchar(*str++); 13 | } 14 | 15 | int puts ( /* Put a string to the default device */ 16 | const char* str /* Pointer to the string */ 17 | ) 18 | { 19 | __puts(str); 20 | putchar('\n'); 21 | } 22 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/dpi.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define DPI_BASE 0x7e208000 3 | #define DPI_APB_ID 0x44504920 4 | #define DPI_C HW_REGISTER_RW( 0x7e208000 ) 5 | #define DPI_C_MASK 0x0000ffff 6 | #define DPI_C_WIDTH 16 7 | #define DPI_C_RESET 0x00003000 8 | -------------------------------------------------------------------------------- /sign.js: -------------------------------------------------------------------------------- 1 | // usage: node sign.js lk.bin recovery.bin 2 | var fs = require("fs"); 3 | var crypto = require("crypto"); 4 | 5 | console.log(process.argv); 6 | 7 | var input = process.argv[2]; 8 | var output = process.argv[3]; 9 | var key = Buffer.from(process.argv[4], "hex"); 10 | 11 | blob = fs.readFileSync(input); 12 | 13 | var hmac = crypto.createHmac("sha1", key); 14 | hmac.update(blob); 15 | var signature = hmac.digest(); 16 | 17 | var signed = Buffer.concat([blob, signature]); 18 | console.log("writing to",output); 19 | fs.writeFileSync(output, signed); 20 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/apb_arbiter_control.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define ACR_BASE 0x7e80a000 3 | #define ACR_APB_ID 0x61726272 4 | #define ACR_control HW_REGISTER_RW( 0x7e80a000 ) 5 | #define ACR_control_MASK 0x0000ffff 6 | #define ACR_control_WIDTH 16 7 | #define ACR_control_RESET 0000000000 8 | -------------------------------------------------------------------------------- /docs/cpuid.txt: -------------------------------------------------------------------------------- 1 | rpi1: 2 | 0x4000104 rpi0 with wifi and headers 3 | 0x4000104 rpi1 with composite video 4 | 0x4000104 rpi1 with composite video and i2s header 5 | 6 | rpi2: 7 | 0x4000140 rpi2 model b v1.1 2014 no composite, no wifi 8 | 9 | rpi3: 10 | 0x4000140 rpi3 with wifi 11 | 12 | 13 | rpi4: 14 | 0x4000160 mentioned in bootcode 2020-05-15 15 | 0x4000161 mentioned in bootcode 2020-05-15, potentially has 2 different mask roms 16 | 0x4000161 found on a B0T pi4b 17 | 0x4000162 bootcode-2020-05-15 checks for this cpuid, if present, .text.firmware_rev[0] bit 0 must be set 18 | 0x4000162 found on a C0 pi400 19 | -------------------------------------------------------------------------------- /docs/sd.txt: -------------------------------------------------------------------------------- 1 | pi2 wont boot with larger clusters 2 | larger clusters give better read performance 3 | mkdosfs -s 32 /dev/mmcblk0p1 4 | 5 | [root@system76:~]# cat /sys/kernel/debug/mmc0/ios 6 | view the SD bus state on linux 7 | 8 | 9 | https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=284261 10 | pi4 ddr50 stuff 11 | 12 | 13 | https://www.raspberrypi.org/forums/viewtopic.php?t=241182 14 | https://www.raspberrypi.org/forums/viewtopic.php?p=1777011 15 | https://goughlui.com/static/multicid.htm 16 | https://goughlui.com/2014/01/02/project-read-collect-decode-sd-card-cid-register-data/ 17 | CID decoding 18 | -------------------------------------------------------------------------------- /docs/pcie.txt: -------------------------------------------------------------------------------- 1 | from the linux dtb file: reg = <0x0 0x7d500000 0x9310>, 2 | 3 | from start4.elf: 4 | vid: 7d50_8000 5 | pid: 7d50_8002 6 | for the vl805 detection 7 | 8 | 2020-05-25 11:27:12 < doug16k> if it is, it's basically a flat array of every possible bus/slot/function with 4KB for each 9 | 2020-05-25 11:27:56 < clever> if its 4kb each, then +0x8000 would just be slot 8 (zero based indexing) 10 | 2020-05-25 11:28:32 < clever> and lspci claims its on bus 1, so 8 slots (0-7) spent on bus 0 (the root hub?) 11 | 2020-05-25 11:29:07 < doug16k> usually it's huge, but I've only seen it on giant desktop machines 12 | 13 | -------------------------------------------------------------------------------- /bootloader.nix: -------------------------------------------------------------------------------- 1 | { lib, config, pkgs, ... }: 2 | 3 | { 4 | options = { 5 | boot.loader.openpi = { 6 | enable = lib.mkOption { 7 | type = lib.types.bool; 8 | default = false; 9 | }; 10 | }; 11 | }; 12 | config = lib.mkIf config.boot.loader.openpi.enable { 13 | system.boot.loader.id = "openpi"; 14 | system.build.installBootLoader = pkgs.substituteAll { 15 | src = ./install-openpi.sh; 16 | name = "install-openpi.sh"; 17 | isExecutable = true; 18 | bootdir = (import ./. {}).arm7.bootdir; 19 | crossShell = pkgs.runtimeShell; 20 | }; 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /docs/stepping.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1761440#p1761440 2 | > No it doesn't. You can't buy a Pi 4B 8GB C0 3 | 4 | 5 | https://www.raspberrypi.org/forums/viewtopic.php?p=1772727#p1772727 6 | > Doing even an A0 and a B0 spin of the chip and testing once back is generally at least 6 months per spin. Getting a B0 chip that works and is suitable for production is actually a fairly impressive task. 7 | > I recall a tale of one chip ending up being on something like G3 (7th full respin, and 3rd metal layer mod) before it worked - how they funded that one I don't know! 8 | 9 | 10 | B1 adds RSA signatures 11 | -------------------------------------------------------------------------------- /common/include/pll_read.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | extern uint32_t xtal_freq; 7 | 8 | uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac); 9 | uint32_t clk_get_input_freq(volatile uint32_t *ctlreg); 10 | uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg); 11 | uint32_t get_vpu_per_freq(void); 12 | uint32_t get_uart_base_freq(void); 13 | uint32_t plla(void); 14 | uint32_t pllb(void); 15 | uint32_t pllc(void); 16 | uint32_t plld(void); 17 | uint32_t pllh(void); 18 | uint32_t pllc_core0(void); 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /docs/bluetooth.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1708780 2 | > Pi 4 doesn't support any of these optional features. It uses the same BCM43455 that was in the 3B+ with a RAM patch that changes the Bluetooth version from 4.1 to 5.0. This allowed it to be recertified as Bluetooth 5.0 compatible. The patch memory is tiny and there isn't enough space to add any of the optional features. You need hardware support for some of them anyway. 3 | 4 | https://discordapp.com/channels/620838168794497044/672272612008787993/779366573973438504 5 | > also, RTS must be held LOW if no hardware flow control is used, or the chip will not respond 6 | 7 | -------------------------------------------------------------------------------- /systemd.patch: -------------------------------------------------------------------------------- 1 | diff -ru systemd-source-orig/src/basic/fd-util.c systemd-source/src/basic/fd-util.c 2 | --- systemd-source-orig/src/basic/fd-util.c 2020-01-26 06:30:03.635836180 -0400 3 | +++ systemd-source/src/basic/fd-util.c 2020-01-26 18:14:23.926389160 -0400 4 | @@ -62,6 +62,7 @@ 5 | 6 | if (fd >= 0) { 7 | PROTECT_ERRNO; 8 | + printf("safe_close(%u) %p\r", fd, __builtin_return_address(0)); 9 | 10 | /* The kernel might return pretty much any error code 11 | * via close(), but the fd will be closed anyway. The 12 | Only in systemd-source/src/basic: .fd-util.c.swp 13 | -------------------------------------------------------------------------------- /utils/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS := -g `${PKG_CONFIG} --cflags libdrm` 2 | CXXFLAGS := ${CFLAGS} 3 | 4 | ramdumper: ramdumper.cc 5 | ${CC} -o $@ $< -lcommon 6 | 7 | pv_dumper.o: pv_dumper.cc 8 | 9 | pv_dumper: pv_dumper.o map_peripherals.o 10 | ${CC} -o $@ $^ -lcommon -lbcm_host -Wall ${CFLAGS} 11 | 12 | pll-inspector.o: pll-inspector.cpp 13 | ${CC} -c -o $@ $< -fpermissive 14 | 15 | pll-inspector: pll-inspector.o map_peripherals.o 16 | ${CC} -o $@ $^ -lbcm_host -lcommon 17 | 18 | kms-test: kms-test.o 19 | ${CXX} -o $@ $^ -ldrm -lm 20 | 21 | install: ramdumper pv_dumper pll-inspector kms-test 22 | mkdir -pv ${out}/bin 23 | cp -vi $^ ${out}/bin/ 24 | -------------------------------------------------------------------------------- /common/include/panic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | extern void panic(const char* fmt, ...) 8 | __attribute__((noreturn)) 9 | __attribute__ ((format (printf, 1, 2))); 10 | 11 | #define panic_plain(ex, ...) \ 12 | (panic)(ex, ## __VA_ARGS__) 13 | #define __STRINGIFY(x) #x 14 | #define LINE_NUMBER(x) __STRINGIFY(x) 15 | #define PANIC_LOCATION __FILE__ ":" LINE_NUMBER(__LINE__) 16 | #define panic(ex, ...) \ 17 | (panic)(# ex "@" PANIC_LOCATION, ## __VA_ARGS__) 18 | 19 | #define assert(x) if (!(x)) { panic("assertion '%s' failed", #x); } 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif -------------------------------------------------------------------------------- /common/include/runtime.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #ifdef __arm__ 10 | # ifdef BAREMETAL 11 | # define HAS_DYNAMIC_ALLOCATIONS 12 | # endif 13 | #endif 14 | 15 | #ifdef HAS_DYNAMIC_ALLOCATIONS 16 | #include 17 | #endif 18 | 19 | #ifdef __VIDEOCORE4__ 20 | #include 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #define RegToRef(x) reinterpret_cast(&x) 28 | 29 | extern void udelay(uint32_t time); 30 | extern void __cxx_init(); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /docs/cracking-rpi4-hmac.txt: -------------------------------------------------------------------------------- 1 | boot little-kernel start4.elf 2 | 3 | ] dw -b 0x60010218 64 4 | 0x60010218: ________ ________ ________ ________ 5 | 0x60010228: ________ 5c5c5c5c 5c5c5c5c 5c5c5c5c 6 | 0x60010238: 5c5c5c5c 5c5c5c5c 5c5c5c5c 5c5c5c5c 7 | 0x60010248: 5c5c5c5c 5c5c5c5c 5c5c5c5c 5c5c5c5c 8 | 9 | that is the o_key_pad the mask rom left in sram, and the SPI bootcode.bin didnt overwrite 10 | the first 20 bytes, are the master key, xor'd with 5c5c5c5c 11 | 12 | if you xor them again, you will get the key for hmac-sha1 13 | 14 | not currently sure on the rules around sharing this key, so it has been censored out, but others are free to reproduce the work 15 | -------------------------------------------------------------------------------- /bcm2835.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchurl }: 2 | 3 | stdenv.mkDerivation rec { 4 | version = "1.64"; 5 | pname = "bcm2835"; 6 | 7 | src = fetchurl { 8 | url = "http://www.airspayce.com/mikem/bcm2835/bcm2835-${version}.tar.gz"; 9 | sha256 = "06s81540iz4vsh0cm6jwah2x0hih79v42pfa4pgr8kcbv56158h6"; 10 | }; 11 | 12 | # We need this because for some reason, the Makefile doesn't use env var AR 13 | preConfigure = '' 14 | makeFlags="$makeFlags AR=$AR" 15 | ''; 16 | 17 | meta = with stdenv.lib; { 18 | description = "C library for Broadcom BCM 2835 as used in Raspberry Pi"; 19 | homepage = http://www.airspayce.com/mikem/bcm2835/; 20 | }; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /firmware/traps.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "pcb.h" 4 | 5 | void fleh_zero(); 6 | void fleh_misaligned(); 7 | void fleh_dividebyzero(); 8 | void fleh_undefinedinstruction(); 9 | void fleh_forbiddeninstruction(); 10 | void fleh_illegalmemory(); 11 | void fleh_buserror(); 12 | void fleh_floatingpoint(); 13 | void fleh_isp(); 14 | void fleh_dummy(); 15 | void fleh_icache(); 16 | void fleh_veccore(); 17 | void fleh_badl2alias(); 18 | void fleh_breakpoint(); 19 | void fleh_unknown(); 20 | void fleh_irq(); 21 | void print_vpu_state(vc4_saved_state_t* pcb); 22 | void sleh_fatal(vc4_saved_state_t* pcb, uint32_t n); 23 | void sleh_irq(vc4_saved_state_t* pcb, uint32_t tp); 24 | -------------------------------------------------------------------------------- /firmware/drivers/BCM2708ArmControl.hh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct BCM2708ArmControl : IODevice { 4 | BCM2708ArmControl(); 5 | 6 | PowerManagementDomain* pmDomain; 7 | 8 | static inline void bridgeWriteBresp(uint8_t bits); 9 | void bridgeCycleBresp(); 10 | void bridgeStart(bool cycleBrespBits); 11 | void setupClock(); 12 | void setupOtherClocks(); 13 | void patchFirmwareData(struct OtpInfo *info); 14 | void loadInitialCode(struct OtpInfo *info); 15 | void mapBusToArm(uint32_t busAddr, uint32_t armAddr); 16 | void printregs(); 17 | void bzero2(void *addr, size_t len); 18 | void start(struct OtpInfo *info); 19 | virtual void init() override; 20 | }; 21 | 22 | -------------------------------------------------------------------------------- /docs/xhci.txt: -------------------------------------------------------------------------------- 1 | xHC ver: 272 HCS: 01000140 0c0000f1 07ff000a HCC: 0220fe65 2 | bcm controller 3 | 4 | xHC ver: 256 HCS: 05000420 fc000031 00e70004 HCC: 002841eb 5 | vl805 controller 6 | 7 | HCS1 bcm vl805 8 | slots 64 32 9 | interrupters 1 4 10 | ports 1 5 11 | 12 | HCS2 bcm vl805 13 | event ring seg 15 3 14 | scratchpad 1 31 pages 15 | 16 | HCC bcm vl805 17 | 64bit Y Y 18 | BW Neg N Y 19 | ctx size 64 32 20 | port pwr N Y 21 | light rst Y Y 22 | LTC Y Y 23 | NSS N Y 24 | PAE N Y 25 | SPC Y n 26 | SEC Y n 27 | CFC Y n 28 | MaxPSASize 15 4 29 | -------------------------------------------------------------------------------- /docs/arm-jtag.txt: -------------------------------------------------------------------------------- 1 | 2020-01-22 20:11:12 < clever> the jtag signals are available at gpio22-27 (but 26 isnt routed out, missing tdi), and some signals are repeated at gpio 4/5/6/12/13 2 | 2020-01-22 20:11:56 < clever> trst is at 22, rtck is at 6/23, tdo is at 5/24, tck at 25, tdi at 4, and tms at 27 3 | https://sysprogs.com/VisualKernel/tutorials/raspberry/jtagsetup/ 4 | https://github.com/synthetos/PiOCD/wiki/Using-a-Raspberry-Pi-as-a-JTAG-Dongle 5 | https://www.suse.com/c/debugging-raspberry-pi-3-with-jtag/ 6 | https://spin.atomicobject.com/2014/04/01/ethernet-adapter-jtag/ 7 | https://www.raspberrypi.org/forums/viewtopic.php?t=202540 8 | 9 | enable_jtag_gpio=1 configures the jtag pins to the right alt modes 10 | -------------------------------------------------------------------------------- /common/default.nix: -------------------------------------------------------------------------------- 1 | { stdenv, tlsf, lib }: 2 | let 3 | baremetal = stdenv.targetPlatform.system == "arm-none" || stdenv.targetPlatform.system == "vc4-none"; 4 | lut = { 5 | vc4-none = "vpu"; 6 | aarch64-linux = "aarch64"; 7 | aarch64-none = "aarch64"; 8 | arm-none = "arm32"; 9 | armv7l-linux = "arm32"; 10 | armv6l-linux = "arm32"; 11 | }; 12 | in stdenv.mkDerivation { 13 | name = "common"; 14 | src = lib.cleanSource ./.; 15 | propagatedBuildInputs = lib.optional baremetal tlsf; 16 | enableParallelBuilding = true; 17 | hardeningDisable = [ "fortify" "stackprotector" ]; 18 | dontStrip = true; 19 | BAREMETAL = baremetal; 20 | targetArch = lut.${stdenv.targetPlatform.system}; 21 | } 22 | -------------------------------------------------------------------------------- /firmware/drivers/BCM2708PowerManagement.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * VideoCore4_Drivers 3 | * Copyright (c) 2017 Kristina Brooks 4 | * 5 | * BCM2708 power management driver. 6 | */ 7 | 8 | #pragma once 9 | #include 10 | 11 | enum cpr_power_result_t { 12 | kCprSuccess = 0, 13 | kCprPowOkTimeout, 14 | kCprMrDoneTimeout, 15 | kCprOscCountTimeout 16 | }; 17 | 18 | enum cpr_power_domain_t { 19 | kCprPowerDomainImage = 0, 20 | kCprPowerDomainARM, 21 | kCprPowerDomainUSB, 22 | kCprPowerDomainVPU1, 23 | 24 | kCprPowerDomain_MAX 25 | }; 26 | 27 | struct PowerManagementDomain : IODevice { 28 | static PowerManagementDomain* getDeviceForDomain(cpr_power_domain_t domain); 29 | virtual void setReset() = 0; 30 | }; -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | > One core failing to start feels like an arm reset issue. We had this in the early days. Some chips were more susceptible than others. 2 | > The fix involved ensuring one of the stb clocks was running prior to the (synchronous) arm reset. 3 | > So my guess was firmware, and a commit related to changing when clocks were enabled. 4 | 5 | > But that doesn't seem to tie up with either of tests. 6 | 7 | https://github.com/Hexxeh/rpi-firmware/issues/232 8 | 9 | 10 | 11 | > By default in RPiOS gcc is set to generate ARMv6 compatible code so that the resulting executable will run on all models of RPi including the 0 and 1 (which don't have NEON units). 12 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=280934 13 | -------------------------------------------------------------------------------- /docs/ddr4.txt: -------------------------------------------------------------------------------- 1 | https://github.com/raspberrypi/firmware/issues/1375 2 | > There are limits to how quickly the Pi 4 can boot - the SDRAM PHY has quite a lengthy training sequence, several seconds from what I remember. 3 | 4 | 5 | 0x7dc2_0000, ddr4 mmio base? 6 | 0x7dc2_4000, ddr4 offset used in memsys loading 7 | 0x7dc2_6010, ddr4, named it mmio4 8 | 0x7dc2_6100, ddr4 offset used in memsys loading, i named it mmio3 9 | a 6 * 32bit thing gets copied into mmio3? 10 | and then a function is ran? 11 | 12 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=275419&start=25 13 | > 2GB = D9WHZ = MT53D512M32D2DS-053 WT:D = 16Gb 1866MHz 14 | > 4GB = D9WHV = MT53D1024M32D4DT-053 WT:D = 32Gb 1866MHz 15 | > 8GB = D9ZCL = MT53E2G32D4NQ-046 WT:A = 64Gb 2133MHz 16 | 17 | -------------------------------------------------------------------------------- /docs/rpi1-jtag.txt: -------------------------------------------------------------------------------- 1 | enable_jtag_gpio=1 2 | uart_2ndstage=1 3 | gpio=4=a5 4 | gpio=27=a4 5 | gpio=23-25=a4 6 | 7 | root@raspberrypi:~# /home/pi/openocd/src/openocd -s /home/pi/openocd/tcl/ -f rpi4-to-rpi1.tcl 8 | 9 | ssh pi@pi4 -L 3333:localhost:3333 -L 4444:localhost:4444 10 | 11 | [clever@amd-nixos:~/apps/rpi/rpi-open-firmware]$ nix-shell default.nix -A aarch64-shell 12 | [nix-shell:~/apps/rpi/rpi-open-firmware]$ armv7l-unknown-linux-gnueabihf-gdb 13 | (gdb) set style enabled off 14 | (gdb) target remote :3333 15 | (gdb) x/5i $pc 16 | => 0xc03dafd8: bic r3, r2, #-16777216 ; 0xff000000 17 | 0xc03dafdc: bic r3, r3, #14680064 ; 0xe00000 18 | 0xc03dafe0: cmp r3, #0 19 | 0xc03dafe4: beq 0xc03db048 20 | 0xc03dafe8: tst r2, #255 ; 0xff 21 | 22 | -------------------------------------------------------------------------------- /firmware/utils.hh: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | #include "drivers/BCM2708Gpio.hpp" 7 | struct OtpInfo; 8 | 9 | void dump_all_gpio(); 10 | void setup_eth_clock(struct OtpInfo *info); 11 | void gpio_print_snapshot(const bool gpio_level[64], const enum BCM2708PinmuxSetting functions[64]); 12 | void gpio_snapshot(bool gpio_level[64], enum BCM2708PinmuxSetting functions[64]); 13 | void set_pl011_funcs(); 14 | void enable_jtag(void); 15 | void peripheral_scan(); 16 | void test_things(); 17 | void do_irq_test(void); 18 | void setup_tec_clock(void); 19 | void setup_tsens(void); 20 | void print_temp(void); 21 | void set_gp_mode(int mash, int source); 22 | void report_sdram_usage(void); 23 | #ifdef __cplusplus 24 | }; 25 | #endif 26 | -------------------------------------------------------------------------------- /docs/rpi4-dram.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=281380 2 | The LPDDR4 standard has optional support for on-die TRR. 3 | This is the part number for the Micron 4GB SDRAM chip: 4 | https://www.micron.com/support/tools-and-utilities/fbga?fbga=d9whv#pnlFBGA 5 | Registration is required in order to get the datasheet for it. 6 | 7 | As far as I'm aware, the SDRAM controller does not track row open/close counts so TRR isn't implemented. 8 | 9 | 10 | Initialising SDRAM 'Samsung' 8Gb x1 total-size: 8 Gbit 3200 # 1gig model?? 11 | Initialising SDRAM 'Samsung' 16Gb x1 total-size: 16 Gbit 3200 # 2gig model?? 12 | Initialising SDRAM 'Micron' 16Gb x2 total-size: 32 Gbit 3200 # 4gig model 13 | Initialising SDRAM 'Micron' 32Gb x2 total-size: 64 Gbit 3200 # 8gig model?? 14 | 15 | -------------------------------------------------------------------------------- /arm_chainloader/memory_map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MEM_CODE_END 0x20000 4 | 5 | #define MEM_STACK_SIZE 0x4000 6 | // stack0 end 7 | #define MEM_STACK_END (MEM_CODE_END + MEM_STACK_SIZE) 8 | 9 | #define MEM_HEAP_START MEM_CODE_END + (MEM_STACK_SIZE*4) 10 | #define MEM_HEAP_SIZE 0x100000 11 | #define MEM_HEAP_END (MEM_HEAP_START + MEM_HEAP_SIZE) 12 | 13 | #define MEM_USABLE_START MEM_HEAP_END 14 | 15 | /* 16 | * 0-50kb .text .data .bss 17 | * 128kb MEM_CODE_END 18 | * 0x20000 (128kb) to 23fff stack0 19 | * 0x24000 to 0x27fff stack1 20 | * 0x28000 to 0x2bfff stack2 21 | * 0x2c000 to 0x2ffff stack3 22 | * 0x30000 to 0x130000 heap 23 | * 32mb (KERNEL_LOAD_ADDRESS) start of kernel 24 | * 250mb (DTB_LOAD_ADDRESS) start of dtb file 25 | */ 26 | -------------------------------------------------------------------------------- /board-details/rpi2-1077df95.txt: -------------------------------------------------------------------------------- 1 | OTP17: 0x1020000a 2 | 19.2mhz crystal present 3 | SDIO pullups should be on? 4 | SD card boot enabled 5 | USB device boot enabled 6 | 7 | SoC serial# 0x1077df95 8 | 9 | HW revision: 0x00a21041 10 | Type: 4 11 | Rev: 1 12 | Proc: 1 13 | Manufacturer: 2 14 | Ram: 2 15 | 16 | Optional Mac Override: 000000000 17 | 18 | OTP66: 0x00000000 19 | 20 | 21 | rpi 2 b rev 1 1gig, embest 22 | 23 | name size encoding WT WB RA WA Sets Assoc LineSize 24 | L1d 32 KB 0x700fe01a 0 1 1 1 0x7f 0x3 0x2(64 bytes) 25 | L1i 32 KB 0x203fe009 0 0 1 0 0x1ff 0x1 0x1(32 bytes) 26 | L2 512 KB 0x707fe03a 0 1 1 1 0x3ff 0x7 0x2(64 bytes) 27 | -------------------------------------------------------------------------------- /docs/rpi4-ethernet-phy.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1691385#p1691385 2 | > "There are 3 ethernet PHY power states that you enter based on various conditions. The first is active/transmitting - when there is traffic, the PHY is fully powered and sending/receiving data. The second is auto-GREEN mode, where the PHY enters a transparent energy-efficient mode when there is no active traffic (stops sending idle symbols and powers down a lot of the TX circuitry, and enters a sleep mode on the RX side). This requires a compatible Energy-Efficient Ethernet link partner, but most switches implement this feature by default. The third is with the cable unplugged - the PHY enters "energy detect" idle which will completely powers down TX and most of RX, periodically waking the RX side to check for cable insertion." 3 | 4 | -------------------------------------------------------------------------------- /firmware/vc4_include/cpu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | static inline void __attribute__((noreturn)) _hang_cpu() { 7 | #if 0 8 | /* disable interrupts */ 9 | __asm__ __volatile__ ("di"); 10 | 11 | /* loop */ 12 | for (;;) { 13 | __asm__ __volatile__ ("nop"); 14 | } 15 | #else 16 | __asm__ __volatile__ ("di"); 17 | // disable every external interrupt 18 | volatile uint32_t *maskreg = (volatile uint32_t*)(IC0_BASE + 0x10); 19 | for (int i=0; i<8; i++) maskreg[i] = 0; 20 | maskreg = (volatile uint32_t*)(IC1_BASE + 0x10); 21 | for (int i=0; i<8; i++) maskreg[i] = 0; 22 | // go to sleep forever (shouldnt need a loop, but just to be safe) 23 | while (true) { 24 | __asm__ __volatile__ ("sleep"); 25 | } 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /docs/hdmi.txt: -------------------------------------------------------------------------------- 1 | pi4: 2 | https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=281606 3 | > You should be able to plug in two 4K displays (or 2x1080p or whatever) and it shoud just work. 4 | > The only difference is that the first port (1) is capable of 4kp60 whereas port 2 can only do 4kp30. If using both you are limited to 30 on both. 5 | 6 | 7 | https://www.raspberrypi.org/forums/viewtopic.php?p=1728940#p1728940 8 | > HDMI < 2.0 maxes out at 300MHz, and this is described in one part of the EDID. 9 | > HDMI >= 2.0 have to support scrambling as a spread spectrum EMC-reduction step, and that is described in the HF-VSDB (HDMI Forum Vendor Specific Data Block) of the EDID. 10 | 11 | 4f5f9d02246 firmware: hdmi: HDMI SM clock must not run slower than audio MAI clock See: https://github.com/raspberrypi/firmware/issues/1295 12 | 13 | -------------------------------------------------------------------------------- /docs/bcm_xhci.txt: -------------------------------------------------------------------------------- 1 | https://discordapp.com/channels/620838168794497044/672272612008787993/780848911920529420 2 | Device (XHC1) 3 | { 4 | Name (_HID, "PNP0D10") // _HID: Hardware ID 5 | Name (_UID, 0x01) // _UID: Unique ID 6 | Name (_CCA, 0x00) // _CCA: Cache Coherency Attribute 7 | 8 | Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings 9 | { 10 | Memory32Fixed (ReadWrite, 11 | 0xfe9c0000, // Address Base (MMIO) 12 | 0x100000, // Address Length 13 | ) 14 | Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive, ,, ) 15 | { 16 | 208 17 | } 18 | }) 19 | } 20 | 21 | -------------------------------------------------------------------------------- /jtag/rpi4-to-rpi2.tcl: -------------------------------------------------------------------------------- 1 | #source [find interface/sysfsgpio-raspberrypi.cfg] 2 | 3 | adapter driver sysfsgpio 4 | sysfsgpio_jtag_nums 11 25 10 9 5 | sysfsgpio_trst_num 7 6 | 7 | set _CHIPNAME rpi2 8 | 9 | transport select jtag 10 | 11 | set _DAP_TAPID 0x4ba00477 12 | 13 | jtag newtap $_CHIPNAME tap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -enable 14 | dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap 15 | 16 | set _TARGETNAME $_CHIPNAME.a7 17 | 18 | set DBGBASE {0x80010000 0x80012000 0x80014000 0x80016000} 19 | set _cores 4 20 | 21 | for { set _core 0 } { $_core < $_cores } { incr _core } { 22 | 23 | target create $_TARGETNAME.$_core cortex_a -dap $_CHIPNAME.dap -coreid $_core -dbgbase [lindex $DBGBASE $_core] 24 | 25 | $_TARGETNAME.$_core configure -event reset-assert-post "cortex_a dbginit" 26 | $_TARGETNAME.$_core configure -event gdb-attach { halt } 27 | } 28 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/perfmon.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define PRM_BASE 0x7e20d000 3 | #define PRM_CS HW_REGISTER_RW( 0x7e20d000 ) 4 | #define PRM_CS_MASK 0xffffffff 5 | #define PRM_CS_WIDTH 32 6 | #define PRM_CV HW_REGISTER_RW( 0x7e20d004 ) 7 | #define PRM_CV_MASK 0xffffffff 8 | #define PRM_CV_WIDTH 32 9 | #define PRM_SCC HW_REGISTER_RW( 0x7e20d008 ) 10 | #define PRM_SCC_MASK 0xffffffff 11 | #define PRM_SCC_WIDTH 32 12 | -------------------------------------------------------------------------------- /tools/wslstage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2017 Kristina Brooks 3 | 4 | # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 5 | # ! DO NOT CHANGE OR REMOVE THIS FILE ! 6 | # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 7 | 8 | import subprocess 9 | import os 10 | from StringIO import StringIO 11 | 12 | disk_name = 'F' 13 | disk_ready = False 14 | wmic_output = os.popen('wcmd wmic logicaldisk get caption, filesystem') 15 | 16 | for line in wmic_output: 17 | if '%s:' % disk_name in line and 'FAT' in line: 18 | disk_ready = True 19 | 20 | if disk_ready: 21 | print('Windows disk %s:\\ is ready!' % disk_name) 22 | print('Copying bootcode.bin to %s:\\ ...\n' % disk_name) 23 | 24 | os.system('''wcmd xcopy /s /y "C:\\Users\\k\\VC4_Firmware\\rpi-open-firmware\\build\\bootcode.bin" "''' + disk_name + ''':\\bootcode.bin"''') 25 | else: 26 | print('Windows disk %s:\\ is not ready!' % disk_name) 27 | 28 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/fatfs/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.12 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | history.txt Revision history. 8 | ffconf.h Configuration file for FatFs module. 9 | ff.h Common include file for FatFs and application module. 10 | ff.c FatFs module. 11 | diskio.h Common include file for FatFs and disk I/O module. 12 | diskio.c An example of glue function to attach existing disk I/O module to FatFs. 13 | integer.h Integer type definitions for FatFs. 14 | option Optional external functions. 15 | 16 | 17 | Low level disk I/O module is not included in this archive because the FatFs 18 | module is only a generic file system layer and not depend on any specific 19 | storage device. You have to provide a low level disk I/O module that written 20 | to control the target storage device. 21 | 22 | -------------------------------------------------------------------------------- /common/Makefile: -------------------------------------------------------------------------------- 1 | all: libcommon.a 2 | 3 | FPUFLAGS=-mfpu=vfp -mfloat-abi=softfp 4 | ARMCFLAGS=-mtune=arm1176jzf-s -march=armv6zk 5 | CFLAGS = -Ilib -I. -Iinclude -ffunction-sections -Wall -g 6 | 7 | OBJS=hexdump.o crc32.o pl011.o 8 | 9 | ifeq (${BAREMETAL},1) 10 | OBJS += hardware.o panic.o cxx_runtime.o print_timestamp.o IODevice.o udelay.o BCM2708Gpio.o 11 | CFLAGS += -nostdlib -nostartfiles -ffreestanding -DBAREMETAL 12 | ARMCFLAGS += -mthumb ${FPUFLAGS} 13 | else 14 | CFLAGS2=${BASECFLAGS} 15 | endif 16 | 17 | ifeq (${targetArch},arm32) 18 | CFLAGS += ${ARMCFLAGS} 19 | endif 20 | 21 | CXXFLAGS=${CFLAGS} -fno-exceptions -fno-rtti 22 | LFLAGS=-nostdlib -nostartfiles -ffreestanding 23 | 24 | 25 | libcommon.a: ${OBJS} 26 | ${AR} rcs $@ $^ 27 | 28 | install: libcommon.a 29 | mkdir -pv ${out}/lib 30 | cp -r include/ ${out}/ 31 | cp -r hardware.h broadcom ${out}/include/ 32 | cp libcommon.a ${out}/lib/ 33 | -------------------------------------------------------------------------------- /docs/dsi.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1758227#p1758227 2 | > Raspberry Pi 7" DSI panel support is now up as a PR for 5.9 and 5.10 kernels - https://github.com/raspberrypi/linux/pull/3954 and https://github.com/raspberrypi/linux/pull/3955. 3 | > This is currently only working on Pi0-3 (tested on Pi3). Pi4 is still to come. 4 | 5 | 6 | https://www.raspberrypi.org/forums/viewtopic.php?f=98&t=290497&start=25 7 | > http://www.tek.com/dl/61W_25772_0_HR.pdf gives you a background to the D-PHY layer for DSI and CSI. Low power states that can be switched to either during H&V blanking, just V blanking, or never. 8 | > Wiki gives a very basic summary - https://en.wikipedia.org/wiki/Display_Serial_Interface 9 | 10 | 11 | https://www.raspberrypi.org/forums/viewtopic.php?p=1768417#p1768417 12 | > http://rfmw.em.keysight.com/mod/pdf/axie_u4421a_mipi_d-phy_protocol_fundamentals_detailed_presentation.pdf 13 | -------------------------------------------------------------------------------- /common/include/drivers/BCM2708Gpio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * VideoCore4_Drivers 5 | * Copyright (c) 2017 Authors of rpi-open-firmware 6 | * 7 | * USB PHY initialization driver. 8 | */ 9 | 10 | #include 11 | 12 | #define GPIO_TAG 0x4750494f 13 | 14 | enum BCM2708PinmuxSetting { 15 | kBCM2708PinmuxIn = 0, 16 | kBCM2708PinmuxOut = 1, 17 | kBCM2708Pinmux_ALT5 = 2, 18 | kBCM2708Pinmux_ALT4 = 3, 19 | kBCM2708Pinmux_ALT0 = 4, 20 | kBCM2708Pinmux_ALT1 = 5, 21 | kBCM2708Pinmux_ALT2 = 6, 22 | kBCM2708Pinmux_ALT3 = 7 23 | }; 24 | 25 | #ifdef __cplusplus 26 | struct BCM2708Gpio { 27 | void setFunction(uint8_t pin, BCM2708PinmuxSetting function); 28 | void getAllFunctions(BCM2708PinmuxSetting *functions); 29 | void clearPin(uint8_t pin); 30 | void setPin(uint8_t pin); 31 | bool getPin(uint8_t pin); 32 | uint32_t getBank(uint8_t bank); 33 | }; 34 | 35 | extern BCM2708Gpio gGPIO; 36 | #endif 37 | -------------------------------------------------------------------------------- /board-details/rpi3-9080d9b6.txt: -------------------------------------------------------------------------------- 1 | OTP17: 0x3020000a 2 | 19.2mhz crystal present 3 | SDIO pullups should be on? 4 | SD card boot enabled 5 | USB device boot enabled 6 | USB host boot enabled (ethernet/mass-storage) 7 | 8 | SoC serial# 0x9080d9b6 9 | 10 | HW revision: 0x00a22082 11 | Type: 8 12 | Rev: 2 13 | Proc: 2 14 | Manufacturer: 2 15 | Ram: 2 16 | 17 | Optional Mac Override: 000000000 18 | 19 | OTP66: 0x00009daa 20 | ETH_CLK on GPIO42 21 | ETH_CLK 25mhz 22 | LAN_RUN on GPIO29 23 | 24 | 25 | rpi 3b rev 2 1gig, embest 26 | 27 | MIDR: 0x410fd034 28 | name size encoding WT WB RA WA Sets Assoc LineSize 29 | L1d 32 KB 0x700fe01a 0 1 1 1 0x7f 0x3 0x2(64 bytes) 30 | L1i 32 KB 0x201fe00a 0 0 1 0 0xff 0x1 0x2(64 bytes) 31 | L2 512 KB 0x703fe07a 0 1 1 1 0x1ff 0xf 0x2(64 bytes) 32 | -------------------------------------------------------------------------------- /my-init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char **argv) { 12 | int status; 13 | //status = mknod("/dev/ttyAMA0", S_IFCHR | 0666, makedev(204,64)); 14 | status = mknod("/dev/kmsg", S_IFCHR | 0666, makedev(1,11)); 15 | if (status) return 1; 16 | int fd = open("/dev/kmsg", O_RDWR); 17 | if (fd < 0) { 18 | printf("failed to open kmsg: %s\n", strerror(errno)); 19 | } 20 | status = dup2(fd, 0); 21 | if (status < 0) return 3; 22 | status = dup2(fd, 1); 23 | if (status < 0) return 40; 24 | status = dup2(fd, 2); 25 | if (status < 0) return 50; 26 | close(fd); 27 | status = write(1, "hello world\n", 12); 28 | if (status != 12) return 60; 29 | status = printf("and now with printf\n"); 30 | if (status < 0) return 70; 31 | return 43; 32 | } 33 | -------------------------------------------------------------------------------- /common/crc32.c: -------------------------------------------------------------------------------- 1 | // from https://rosettacode.org/wiki/CRC-32#Implementation_2 2 | #include 3 | #include 4 | #include 5 | 6 | uint32_t rc_crc32(uint32_t crc, const char *buf, size_t len) { 7 | static uint32_t table[256]; 8 | static int have_table = 0; 9 | uint32_t rem; 10 | uint8_t octet; 11 | int i, j; 12 | const char *p, *q; 13 | 14 | /* This check is not thread safe; there is no mutex. */ 15 | if (have_table == 0) { 16 | /* Calculate CRC table. */ 17 | for (i = 0; i < 256; i++) { 18 | rem = i; /* remainder from polynomial division */ 19 | for (j = 0; j < 8; j++) { 20 | if (rem & 1) { 21 | rem >>= 1; 22 | rem ^= 0xedb88320; 23 | } else 24 | rem >>= 1; 25 | } 26 | table[i] = rem; 27 | } 28 | have_table = 1; 29 | } 30 | 31 | crc = ~crc; 32 | q = buf + len; 33 | for (p = buf; p < q; p++) { 34 | octet = *p; /* Cast to unsigned octet. */ 35 | crc = (crc >> 8) ^ table[(crc & 0xff) ^ octet]; 36 | } 37 | return ~crc; 38 | } 39 | -------------------------------------------------------------------------------- /docs/v3d.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1817706#p1817706 2 | > Pi0-3 use T-format for textures into V3D. 3 | > Pi4 uses UIF format, but has a hardware block (the Texture Formatter Unit or TFU) to convert other formats into UIF efficiently. That said it's just been noted that NV12/21 haven't been using the hardware - that's being fixed. 4 | 5 | > The YUYV family of YUV4:2:2 formats are generally not supported by anything other than the ISP. 6 | > Mesa hides the conversions from you, so whilst it may say that it can import format X, it may not be an efficient import :-/ 7 | 8 | 9 | https://www.raspberrypi.org/forums/viewtopic.php?f=38&t=320638 10 | > Pi4 will take YUV in through the TFU (Texture Formatter Unit) to create a texture. I think Pi3 has a shader which will do the same thing. 11 | > Yes the TFU is hardware. The Pi4 3D block needs all textures in UIF format, so even RGB source images go through it. 12 | 13 | 14 | v3d can render to both linear and tiled (t-format or uif) formats 15 | -------------------------------------------------------------------------------- /arm_chainloader/linker.lds: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | . = 0x0; 4 | 5 | _text = .; 6 | 7 | .text : { 8 | *(.text) 9 | *(.text.*) 10 | *(.gnu.warning) 11 | } 12 | 13 | _etext = .; 14 | 15 | .rodata : { *(.rodata) *(.rodata.*) } 16 | . = ALIGN(4096); 17 | _erodata = .; 18 | 19 | . = ALIGN(32 / 8); 20 | 21 | PROVIDE (__init_array_start = .); 22 | .init_array : { 23 | KEEP(*(.init_array)) 24 | KEEP(*(.init_array.*)) 25 | } 26 | PROVIDE (__init_array_end = .); 27 | 28 | .data : { /* Data */ 29 | *(.data) 30 | } 31 | 32 | .bss : { 33 | _edata = .; 34 | __bss_start = .; 35 | *(.bss.page_table) 36 | *(.bss) 37 | *(.bss.*) 38 | __bss_end = .; 39 | } 40 | 41 | . = ALIGN(16); 42 | _irq_stack_bottom = .; 43 | . = . + 1024; 44 | _irq_stack_top = .; 45 | 46 | _svc_stack_bottom = .; 47 | . = . + 1024; 48 | _svc_stack_top = .; 49 | 50 | . = ALIGN(16); 51 | _end = . ; 52 | } 53 | -------------------------------------------------------------------------------- /utils/ramdumper.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main(int argc, char **argv) { 12 | if (argc < 2) { 13 | fprintf(stderr, "usage: %s \n", argv[0]); 14 | return 1; 15 | } 16 | uint32_t addr = strtoll(argv[1], NULL, 0); 17 | addr = (addr >> 12) << 12; 18 | int length = 0x1000; 19 | 20 | if (argc >= 3) { 21 | length = strtol(argv[2], NULL, 0); 22 | } 23 | 24 | int fd = open("/dev/mem", O_RDWR); 25 | if (fd < 0) { 26 | perror("unable to open /dev/mem"); 27 | return 2; 28 | } 29 | volatile void *rawaddr = (uint32_t*)mmap(NULL, length, PROT_READ, MAP_SHARED, fd, addr); 30 | if (rawaddr == MAP_FAILED) { 31 | perror("unable to mmap"); 32 | return 3; 33 | } 34 | printf("starting at 0x%x (%dMB)\n", addr, addr/1024/1024); 35 | hexdump_ram(rawaddr, addr, length); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /utils/map_peripherals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "map_peripherals.h" 13 | 14 | #define VC 4 15 | 16 | void open_peripherals(struct peripherals &handle) { 17 | int fd = open("/dev/mem", O_RDWR); 18 | if (fd < 0) { 19 | perror("unable to open /dev/mem"); 20 | exit(1); 21 | } 22 | uint32_t arm_phys = bcm_host_get_peripheral_address(); 23 | #if VC == 6 24 | arm_phys = 0xfe000000; 25 | #endif 26 | printf("arm physical is at 0x%x\n", arm_phys); 27 | uint32_t *rawaddr = (uint32_t*)mmap(NULL, 16 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, arm_phys); 28 | if (rawaddr == MAP_FAILED) { 29 | perror("unable to mmap"); 30 | exit(2); 31 | } 32 | handle.fd = fd; 33 | handle.peripherals_start = rawaddr; 34 | handle.physical_start = arm_phys; 35 | handle.vc = VC; 36 | } 37 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/fatfs/integer.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------*/ 2 | /* Integer type definitions for FatFs module */ 3 | /*-------------------------------------------*/ 4 | 5 | #ifndef _FF_INTEGER 6 | #define _FF_INTEGER 7 | 8 | #ifdef _WIN32 /* FatFs development platform */ 9 | 10 | #include 11 | #include 12 | typedef unsigned __int64 QWORD; 13 | 14 | 15 | #else /* Embedded platform */ 16 | 17 | /* These types MUST be 16-bit or 32-bit */ 18 | typedef int INT; 19 | typedef unsigned int UINT; 20 | 21 | /* This type MUST be 8-bit */ 22 | typedef unsigned char BYTE; 23 | 24 | /* These types MUST be 16-bit */ 25 | typedef short SHORT; 26 | typedef unsigned short WORD; 27 | typedef unsigned short WCHAR; 28 | 29 | /* These types MUST be 32-bit */ 30 | typedef long LONG; 31 | typedef unsigned long DWORD; 32 | 33 | /* This type MUST be 64-bit (Remove this for C89 compatibility) */ 34 | typedef unsigned long long QWORD; 35 | 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/mailbox.hpp: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Mailbox driver. 17 | 18 | =============================================================================*/ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | struct Bcm2708Mailbox { 25 | Bcm2708Mailbox(); 26 | bool write_word(uint32_t data, int timeout = 10000); 27 | }; 28 | 29 | extern Bcm2708Mailbox g_Mailbox; -------------------------------------------------------------------------------- /docs/vpu-l1.txt: -------------------------------------------------------------------------------- 1 | L1_BASE/0x7ee02000 controls the VPU L1 cache 2 | 3 | L1_IC?_CONTROL controls many L1 features, including cache flush 4 | 5 | 6 | L1_IC?_FLUSH_S/L1_IC0_FLUSH_E control the start/end of a region of memory being flushed from L1 7 | 8 | L1_IC?_RD_HITS counter for the number of L1 read hits? 9 | L1_IC?_RD_MISSES and misses 10 | 11 | L1_IC?_BP_HITS 12 | L1_IC?_BP_MISSES another hit/miss pair for something? 13 | 14 | 15 | 16 | unsorted notes: 17 | L1/L2 cache control logic, discovered within https://github.com/itszor/gcc-vc4/blob/vc4-gcc6/gcc/config/vc4/vc4.h#L122-L143 18 | 19 | start by writing a start and end address to L1_D_FLUSH_S and L1_D_FLUSH_E 20 | then set DC0_FLUSH(0x2) and DC1_FLUSH(0x4) flags within L1_D_CONTROL 21 | then poll until those flags self-clear 22 | 23 | similar logic for instruction caches on L1_IC0_CONTROL/L1_IC0_FLUSH_S/L1_IC0_FLUSH_E and L1_IC1_CONTROL/L1_IC1_FLUSH_S/L1_IC1_FLUSH_E but only with START_FLUSH(0x2) as the flag 24 | 25 | L2_FLUSH_STA/L2_FLUSH_END/L2_CONT_OFF also exists, and has a 2bit flush-mode and a 1bit flush flag (0x4) 26 | -------------------------------------------------------------------------------- /firmware/linker.ld: -------------------------------------------------------------------------------- 1 | MEMORY { 2 | ram (rwx) : ORIGIN = 0x00000000, LENGTH = 128K 3 | } 4 | SECTIONS 5 | { 6 | .text : { 7 | . = 0x0; 8 | . += SIZEOF_HEADERS; 9 | . = 0x200; 10 | _text = .; 11 | *(.text.start) 12 | *(.text) 13 | *(.text.*) 14 | *(.gnu.warning) 15 | _etext = .; 16 | } 17 | 18 | .rodata : { 19 | . = ALIGN(512); 20 | *(.rodata.vectorTable) 21 | *(.rodata) 22 | *(.rodata.*) 23 | . = ALIGN(16); 24 | _erodata = .; 25 | } 26 | 27 | 28 | .init_array : { 29 | . = ALIGN(16); 30 | PROVIDE (__init_array_start = .); 31 | KEEP(*(.init_array)) 32 | KEEP(*(.init_array.*)) 33 | KEEP(*(.ctors)) 34 | KEEP(*(.ctors.*)) 35 | __init_array_end = .; 36 | } 37 | 38 | .data : { /* Data */ 39 | *(.data) 40 | _edata = .; 41 | } 42 | 43 | .bss : { 44 | __bss_start = .; 45 | *(.bss) 46 | *(COMMON) 47 | . = ALIGN(32 / 8); 48 | _end = . ; 49 | } 50 | /* First location in stack is highest address in RAM */ 51 | _fstack = ORIGIN(ram) + LENGTH(ram) - 4; 52 | } 53 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/README.txt: -------------------------------------------------------------------------------- 1 | This dir contains all the register map files for the design 2 | The bulk of it is created with the create_regs script (run create_regs) which 3 | parses the *_regs files in the hdl dirs and creates the individual files 4 | 5 | The top level file is chip/hdl/bcm2708_regs.tcl which defines the contents 6 | and off sets of the chip level memory map. 7 | 8 | Create regs then searches the dir tree for each object mentioned in bcm2708_regs.tcl 9 | and locates its "object_regs.tcl" file 10 | 11 | It then generates all the .h .inc ... files. 12 | 13 | These are then all lumped together in a register_map.h register_map.inc etc file 14 | 15 | 16 | 17 | The general procedure to modify this is 18 | 19 | 20 | 21 | check out all of chip/verification/code/vcinclude 22 | run create_regs in this dir 23 | revert all unchanged files in vcinclude 24 | check the modified ones and checkl them in if they are ok. 25 | 26 | 27 | Note: 28 | If create regs cant find a _regs.tcl file it will crash 29 | If it finds two files with the same name it will crash 30 | -------------------------------------------------------------------------------- /docs/vpu-jtag.txt: -------------------------------------------------------------------------------- 1 | J5 on rpi2, vpu jtag, 8 pins 2 | J5 on rpi4b, vpu jtag, 0.5mm pitch 8 pins 3 | 4 | use this one 5 | 1 TCK 8 6 | 2 GND 7 7 | 3 TMS 6 8 | 4 TDO 5 9 | 5 GND 4 10 | 6 TDI 3 11 | 7 TRST_N 2 12 | 8 RUN 1 13 | 14 | 15 | > I think I have had one SD card corruption due to power pulling, but MANY SD card corruptions from using the JTAG debugger on the Videocore and forgetting to shutdown correctly. This is because the JTAG stops all the cores, even during SD card writes. 16 | 17 | https://www.raspberrypi.org/forums/viewtopic.php?p=1750304#p1750304 18 | 19 | 20 | https://www.raspberrypi.org/forums/viewtopic.php?p=1808846#p1808846 21 | > I don't know why people think this is difficult to work with. Seems to work fine to me, but then I am using the recommend setup - Pi4, OpenOCD, Pico. Sometimes use VSCode, sometimes the command line. It all just works. Compared with dev systems I have used in the past, it's a joy! The only embedded system that I've used that is better is the one for the VideoCore, which is very good, but costs a lot. 22 | 23 | -------------------------------------------------------------------------------- /jtag/rpi4-to-rpi3.tcl: -------------------------------------------------------------------------------- 1 | #source [find interface/sysfsgpio-raspberrypi.cfg] 2 | 3 | adapter driver sysfsgpio 4 | sysfsgpio_jtag_nums 11 25 10 9 5 | sysfsgpio_trst_num 7 6 | 7 | set _CHIPNAME rpi3 8 | 9 | transport select jtag 10 | 11 | set _DAP_TAPID 0x4ba00477 12 | 13 | jtag newtap $_CHIPNAME tap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -enable 14 | dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap 15 | 16 | set _TARGETNAME $_CHIPNAME.a53 17 | set _CTINAME $_CHIPNAME.cti 18 | 19 | set DBGBASE {0x80010000 0x80012000 0x80014000 0x80016000} 20 | set CTIBASE {0x80018000 0x80019000 0x8001a000 0x8001b000} 21 | set _cores 4 22 | 23 | for { set _core 0 } { $_core < $_cores } { incr _core } { 24 | cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 0 -ctibase [lindex $CTIBASE $_core] 25 | 26 | target create $_TARGETNAME.$_core aarch64 -dap $_CHIPNAME.dap -coreid $_core -dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core 27 | 28 | $_TARGETNAME.$_core configure -event reset-assert-post "aarch64 dbginit" 29 | $_TARGETNAME.$_core configure -event gdb-attach { halt } 30 | } 31 | -------------------------------------------------------------------------------- /docs/devicetree.txt: -------------------------------------------------------------------------------- 1 | https://gist.github.com/mrvn/a9e596aa4d02a5db0b9d0e8f04ac5b37 2 | a pi4 dtb file 3 | 4 | interrupt maps 5 | https://www.devicetree.org/open-firmware/practice/imap/imap0_9d.pdf 6 | 7 | pci bindings 8 | https://www.devicetree.org/open-firmware/bindings/pci/pci2_1.pdf 9 | 10 | https://elinux.org/images/f/f9/Petazzoni-device-tree-dummies_0.pdf 11 | 12 | https://docs.rs/device_tree/1.1.0/device_tree/ 13 | 14 | overall 15 | https://readthedocs.org/projects/devicetree-specification/downloads/pdf/stable/ 16 | 17 | https://saurabhsengarblog.wordpress.com/2015/11/28/device-tree-tutorial-arm/ 18 | 19 | https://www.kernel.org/doc/Documentation/devicetree/bindings/input/gpio-keys.txt 20 | 21 | cpu release addr 22 | https://android.googlesource.com/kernel/msm/+/android-7.1.0_r0.2/Documentation/devicetree/bindings/arm/cpus.txt#204 23 | 24 | 25 | https://github.com/raspberrypi/rpi-eeprom/pull/273 26 | > /proc/device-tree/chosen/bootloader/version is populated in the latest firmware and should be used in preference to vcgencmd bootloader_versions because it does not depend on VCHI and is non-blocking. 27 | 28 | -------------------------------------------------------------------------------- /docs/pmic.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=236442 2 | 3 | low voltage detection: 4 | https://www.raspberrypi.org/forums/viewtopic.php?p=1724251#p1724251 5 | > 3B+ and 4B poll the PMIC, other devices with under-voltage detection have a simple circuit made of discrete components that drives a GPIO. 6 | 7 | https://www.raspberrypi.org/forums/viewtopic.php?p=1758877#p1758877 8 | > A little bit more information on the low power detection circuit on the Pi4/400 that I didn't know! 9 | > There is a range where the detection is guaranteed to fire, might fire, and wont fire. This is down to the PMIC, nothing to do with us. 10 | > 0-4.52 Will fire 11 | > 4.52-4.65 Might fire 12 | > 4.65-5.1+ Won't fire 13 | > Since 4.52, the guaranteed detection point, is below our PS specification range, we are in the clear here, as before, there is nothing to worry about. 14 | 15 | 16 | CM4 uses MxL7704 17 | 18 | 19 | https://www.raspberrypi.org/forums/viewtopic.php?p=1849000#p1849000 20 | pi4 PMIC schematic info 21 | 22 | 23 | > Da9121 is the cm4/pi400 VCore pmic . Might be handy to know for openfirmware for these 24 | 25 | -------------------------------------------------------------------------------- /docs/revision.txt: -------------------------------------------------------------------------------- 1 | found in a start4.elf, search for +USB_VL805 2 | 3 | gpio expander is present on type codes: 4 | * 0x8 3B 5 | * 0xa CM3 6 | * 0xb 7 | * 0xd 3B+ 8 | * 0xe 3A+ 9 | * 0x10 CM3+ 10 | * 0x11 4B 11 | * 0x13 pi400 12 | * 0x14 CM4 13 | 14 | vl805 present on: 15 | * 0x11 4B 16 | * 0x13 17 | 18 | vl805-eeprom present on: 19 | * 0x11 with revNr < 4 20 | 21 | bluetooth on uart 0: 22 | * 0x8 3B 23 | * 0xb 24 | * 0xc Zero W 25 | * 0xd 3B+ 26 | * 0xe 3A+ 27 | * 0x11 4B 28 | * 0x13 29 | * 0x14 30 | 31 | pmic ncp 6343: 32 | * 0x4 2B 33 | * 0x8 3B 34 | * 0xa CM3 35 | * 0x10 CM3+ 36 | 37 | pmic xr 77004: 38 | * 0xe 3A+ 39 | * 0xd 3B+ 40 | * 0x11 4B 41 | * 0x13 42 | * 0x14 43 | 44 | pmic da 9121: 45 | * 0x13 46 | * 0x14 47 | * 0x11 with 3 < revNr 48 | 49 | sd power switch: (type == 0x11 && (2 Yes, i also assume the PHY is part of the DWC2 IP. Unfortunately we don't have a PHY driver yet, the devicetree fake this via non-op driver. Maybe this is the root cause of this issue. The BCM2835 datasheet provides a register description for MDIO access incl. VBUS interrupt. 4 | > In case you need a datasheet for the DWC2 IP, try to google for Silicon Labs EZR32WG. It seems to use the same core. 5 | 6 | USB_GHWCFG4 says it has hw support for 7 IN's including control 7 | 8 | USB_GHWCFG1: 0x0 9 | USB_GHWCFG2: 0x228ddd50 10 | USB_GHWCFG3: 0xff000e8 11 | USB_GHWCFG4: 0x1ff00020 12 | 13 | uses UTMI+ to connect to phy 14 | 15 | 7 device mode EP's 16 | 8 host mode channels 17 | host mode allows periodic OUT 18 | dynamic fifo size allowed 19 | dedicated fifo per EP/channel 20 | 21 | non-periodic request queue depth, 8 22 | host mode periodic request depth, 8 23 | 24 | 19bit transfer size counters 25 | 10bit packet size counters, hardware max of 1024 bytes per packet? 26 | 4080 x 32bit dfifo depth 27 | -------------------------------------------------------------------------------- /docs/teletext.txt: -------------------------------------------------------------------------------- 1 | https://www.etsi.org/deliver/etsi_i_ets/300700_300799/300706/01_60/ets_300706e01p.pdf 2 | 3 | each symbol is either black or (white * 0.75) 4 | 45 bytes per scanline (including a preamble of 10101010 10101010 11100100, 3rd byte is framing code) 5 | 16 scanlines per field 6 | 2020-06-15 09:54:07 < clever> bit order for the main payload? 7 | 2020-06-15 09:56:33 < ali1234> the LSBit is transmitted first, i just read it 8 | 2020-06-15 09:58:27 < ali1234> if you dont stretch it wont work. the clock run in has to be within a certain tolerance 9 | 10 | 2020-06-15 09:55:17 < ali1234> there are two modes 11 | 2020-06-15 09:55:34 < ali1234> in normal mode there are 16 lines that can contain data but not all have to be filled 12 | 2020-06-15 09:55:45 < ali1234> in full field mode every line contains teletext including picture lines 13 | 2020-06-15 09:56:17 < clever> and the tv will auto-detect that? or it needs a special cmd in the first 16 scanlines? 14 | 2020-06-15 09:56:41 < ali1234> i have never seen a TV that supports full field mode 15 | 2020-06-15 09:56:54 < ali1234> and it needs a special command to enable it yes 16 | 2020-06-15 09:57:09 < ali1234> something in a broadcast service packet iirc 17 | 18 | -------------------------------------------------------------------------------- /hs-gpio/Types.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ExistentialQuantification #-} 2 | 3 | 4 | module Types (Name(FileChoice, MainMenu, Menu1), Dialog(Dialog, dRender, dHandleEvent), AppState(AppState, asLastMsg, asDialogStack, asReplyChan, asMmioWindow), CustomEvent(CustEvtStateUpdate), DialogReply(DialogReplyHalt, DialogReplyContinue, DialogReplyLiftIO), StateUpdate(StateUpdate)) where 5 | 6 | import Brick (Widget, EventM, BrickEvent) 7 | import Brick.BChan (BChan) 8 | import GHC.Ptr 9 | import GPIO 10 | 11 | data Name = MainMenu | FileChoice | Menu1 | None deriving (Eq, Ord, Show) 12 | 13 | data AppState = AppState 14 | { asReplyChan :: BChan CustomEvent 15 | , asLastMsg :: String 16 | , asDialogStack :: Dialog 17 | , asMmioWindow :: Ptr RPI 18 | } 19 | 20 | data DialogReply = DialogReplyHalt AppState | DialogReplyContinue Dialog | DialogReplyLiftIO (IO Dialog) 21 | 22 | data Dialog = Dialog 23 | { dRender :: AppState -> [ Widget Name ] 24 | , dHandleEvent :: AppState -> BrickEvent Name CustomEvent -> EventM Name DialogReply 25 | } 26 | 27 | data StateUpdate = StateUpdate [(Pin, AltMode)] deriving Show 28 | 29 | data CustomEvent = CustEvtStateUpdate StateUpdate deriving Show 30 | -------------------------------------------------------------------------------- /notc/include/xprintf.h: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* Universal string handler for user console interface (C)ChaN, 2011 */ 3 | /*------------------------------------------------------------------------*/ 4 | 5 | #ifdef __arm__ 6 | #include 7 | #else 8 | #include "stdarg.h" 9 | #endif 10 | 11 | 12 | #ifndef _STRFUNC 13 | #define _STRFUNC 14 | 15 | #define _USE_XFUNC_OUT 1 /* 1: Use output functions */ 16 | #define _CR_CRLF 1 /* 1: Convert \n ==> \r\n in the output char */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | //int putchar (int c); 23 | int puts (const char* str); 24 | int printf (const char* fmt, ...) __attribute__ ((format (printf, 1, 2))); 25 | void put_dump (const void* buff, unsigned long addr, int len, int width); 26 | void uart_putc(unsigned int ch); 27 | 28 | 29 | int vprintf ( 30 | const char* fmt, /* Pointer to the format string */ 31 | va_list arp /* Pointer to arguments */ 32 | ); 33 | 34 | #define DW_CHAR sizeof(char) 35 | #define DW_SHORT sizeof(short) 36 | #define DW_LONG sizeof(long) 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /common/include/drivers/IODevice.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | enum IODeviceState { 7 | kIODeviceUninitialized, 8 | kIODeviceStarted, 9 | kIODeviceStopped 10 | }; 11 | 12 | #ifdef __cplusplus 13 | struct IODevice { 14 | const char* driverName; 15 | IODeviceState deviceState; 16 | uint32_t tag; 17 | 18 | IODevice(); 19 | 20 | void driverLog(const char* fnName, const char* fmt, ...); 21 | void registerDriver(); 22 | 23 | void inline setName(const char* name) { 24 | driverName = name; 25 | } 26 | 27 | void inline setTag(uint32_t tag) { 28 | this->tag = tag; 29 | } 30 | 31 | virtual void start(); 32 | virtual void stop(); 33 | virtual void init(); 34 | 35 | void _afterInit(); 36 | void _beforeInit(); 37 | 38 | virtual inline IODeviceState getDeviceState() { 39 | return deviceState; 40 | } 41 | 42 | static IODevice* findByTag(uint32_t tag); 43 | }; 44 | #endif 45 | 46 | #define IODriverLog(fmt, ...) driverLog(__FUNCTION__, fmt, ##__VA_ARGS__) 47 | #define IODriverCreateSingletonInstance(clazz) static clazz __IODriver_static_ ## clazz {} 48 | #define IODriverConstructor(clazz) inline clazz() { _beforeInit(); driverName = #clazz; init(); _afterInit(); } 49 | -------------------------------------------------------------------------------- /common/put_dump.c: -------------------------------------------------------------------------------- 1 | 2 | /*----------------------------------------------*/ 3 | /* Dump a line of binary dump */ 4 | /*----------------------------------------------*/ 5 | 6 | void put_dump ( 7 | const void* buff, /* Pointer to the array to be dumped */ 8 | unsigned long addr, /* Heading address value */ 9 | int len, /* Number of items to be dumped */ 10 | int width /* Size of the items (DF_CHAR, DF_SHORT, DF_LONG) */ 11 | ) 12 | { 13 | int i; 14 | const unsigned char *bp; 15 | const unsigned short *sp; 16 | const unsigned long *lp; 17 | 18 | 19 | printf("%08lX ", addr); /* address */ 20 | 21 | switch (width) { 22 | case DW_CHAR: 23 | bp = buff; 24 | for (i = 0; i < len; i++) /* Hexdecimal dump */ 25 | printf(" %02X", bp[i]); 26 | putchar(' '); 27 | for (i = 0; i < len; i++) /* ASCII dump */ 28 | putchar((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.'); 29 | break; 30 | case DW_SHORT: 31 | sp = buff; 32 | do /* Hexdecimal dump */ 33 | printf(" %04X", *sp++); 34 | while (--len); 35 | break; 36 | case DW_LONG: 37 | lp = buff; 38 | do /* Hexdecimal dump */ 39 | printf(" %08lX", *lp++); 40 | while (--len); 41 | break; 42 | } 43 | 44 | putchar('\n'); 45 | } 46 | -------------------------------------------------------------------------------- /docs/csi.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=43&t=277885 2 | > There is an alternative driver (bcm2835_unicam) that is a pure Linux driver for the csi2 receiver. It purely writes the frames to ram and has no ae or awb control loops, but it can easily support any sensor for which there is a Linux driver. 3 | 4 | https://www.raspberrypi.org/forums/viewtopic.php?p=1724505#p1724505 5 | > The CPU provides the CSI2 receiver peripheral with the address of the buffer to write to, and it then provides an interrupt at the end of frame. 6 | > Forget the firmware. Use the V4L2 drivers ("dtoverlay=imx477" in config.txt) 7 | 8 | https://www.raspberrypi.org/forums/viewtopic.php?p=1789829#p1789829 9 | > The CSI lines meet the MIPI D-PHY spec, so switch voltage based on whether in Low Power (LP) or High Speed (HS) mode. 10 | > OK. Thank you very much. If I am reading what I found correctly, it the LP mode is 1.2V and the HS mode is differential signal swing of a few hundred milivolts. Does that sound about right? 11 | > Also, am I correct in assuming that the clock line signal is generated by the camera module, and is thus an input on the Rasbperry Pi side? 12 | > Yes, all signals within a D-PHY link are in the same direction, from source to sink. 13 | -------------------------------------------------------------------------------- /firmware/drivers/BCM2708ClockDomains.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * VideoCore4_Drivers 3 | * Copyright (c) 2017 Kristina Brooks 4 | * 5 | * PLL VCOs and their channels. 6 | */ 7 | 8 | #pragma once 9 | #include 10 | 11 | struct BCM2708VCO : IODevice { 12 | volatile uint32_t* dig; 13 | volatile uint32_t* ana; 14 | volatile uint32_t* ctrl; 15 | volatile uint32_t* cmPllCtrl; 16 | volatile uint32_t *frac; 17 | 18 | void setDigValues(); 19 | void dumpDigValues(); 20 | void configure(uint32_t ndiv, uint32_t frac, uint32_t pdiv, bool halve); 21 | void write_ana(uint32_t ana[4]); 22 | private: 23 | uint32_t prediv_mask; 24 | uint32_t ana0_mask, ana0_set, ana1_mask, ana1_set, ana3_mask, ana3_set; 25 | uint32_t reference_enable; // for example A2W_XOSC_CTRL_PLLDEN_SET 26 | }; 27 | 28 | struct BCM2835PLLDivider : IODevice { 29 | BCM2835PLLDivider(const char *name, volatile uint32_t *a2w, volatile uint32_t *cm, uint8_t channel); 30 | void configure(uint32_t divisor); 31 | private: 32 | volatile uint32_t *a2w; // for example A2W_PLLC_PER 33 | volatile uint32_t *cm; // for example CM_PLLC 34 | uint8_t channel; // 0/1/2/3, which pair of load/hold bits to use in CM 35 | }; 36 | 37 | extern BCM2835PLLDivider pllc_per; 38 | -------------------------------------------------------------------------------- /official-boot-flow.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | rpi1 -> maskrom1 3 | rpi2 -> maskrom1 4 | rpi2b -> maskrom2 5 | rpi3 -> maskrom2 6 | rpi4 -> maskrom3 7 | 8 | maskrom1 -> sd_bootcode 9 | 10 | maskrom2 -> sd_bootcode [ label="1" ] 11 | maskrom2 -> nand_flash [ label="2" ] 12 | maskrom2 -> spi_flash [ label="3" ] 13 | maskrom2 -> usb_boot [ label="4" ] 14 | 15 | maskrom3 -> sd_recovery [ label="1" ] 16 | maskrom3 -> spi_blob [ label="2" ] 17 | maskrom3 -> usb_device_boot [ label="3" ] 18 | 19 | usb_boot -> usb_host_boot [ label="OTG=0" ] 20 | usb_boot -> usb_device_boot [ label="OTG=1" ] 21 | 22 | usb_host_boot -> usb_bootcode 23 | usb_host_boot -> usb_netboot 24 | 25 | sd_bootcode -> start_elf 26 | usb_bootcode -> start_elf 27 | usb_netboot -> start_elf 28 | 29 | spi_blob -> start4_elf [ label="over SD or tftp" ] 30 | 31 | start_elf -> final 32 | start4_elf -> final 33 | 34 | sd_bootcode [ label="bootcode.bin\non primary SD" ] 35 | usb_bootcode [ label="bootcode.bin\non usb mass-storage" ] 36 | usb_netboot [ label="bootcode.bin\nover tftp\nover LAN951x" ] 37 | start_elf [ label="start.elf" ] 38 | start4_elf [ label="start4.elf" ] 39 | final [ label="load linux and enable arm\nas configured by config.txt" ] 40 | } 41 | -------------------------------------------------------------------------------- /common/panic.c: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Panic routine. 17 | 18 | =============================================================================*/ 19 | 20 | #include 21 | #include 22 | 23 | #if defined(__VIDEOCORE4__) 24 | #include 25 | #else 26 | #include 27 | #endif 28 | 29 | #undef panic 30 | 31 | void panic(const char* fmt, ...) { 32 | printf("panic(): "); 33 | 34 | va_list arp; 35 | 36 | va_start(arp, fmt); 37 | vprintf(fmt, arp); 38 | va_end(arp); 39 | 40 | putchar('\n'); 41 | 42 | hang_cpu(); 43 | } 44 | -------------------------------------------------------------------------------- /docs/i2c.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=286030 2 | > The very earliest Pis used controller 0 for Linux, and controller 1 for the camera. This swapped with the 1B+/1A+. 3 | > The camera should work fine on your 256 and 512MB B's, just be careful to use i2c_vc or i2c_arm in devicetree/config.txt and not explicit controller numbers. 4 | 5 | 6 | https://www.raspberrypi.org/forums/viewtopic.php?p=1744863#p1744863 7 | > Also be aware that I2C-1 and I2C-2 blocks fail to implement clock stretching properly and may not work with some slave devices. 8 | 9 | https://www.raspberrypi.org/forums/viewtopic.php?p=1761407#p1761407 10 | > GPIOs 44&45 are connected to CAM1 and DISP1, and a recent kernel should configure those as /dev/i2c-10 if you add dtparam=i2c_vc=on to config.txt. The fan and RTC are connected to this bus. 11 | 12 | 13 | https://www.raspberrypi.org/forums/viewtopic.php?p=1779231#p1779231 14 | > i2c-0 = controller I2C0 on GPIOs 0 & 1 15 | > i2c-1 = controller I2C1 with no mux - GPIOs 2 & 3 are hard-coded as the only sensible choice 16 | > i2c-10 = controller I2C0 on GPIOs 44 & 45 (or whatever the cameras and displays are configured to use) 17 | > i2c-11 = the I2C0 mux, which end up being on the set of pins last used - it's best to avoid this 18 | 19 | -------------------------------------------------------------------------------- /docs/vcgencmd.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=245733&p=1500079&hilit=measure_volts+usb_pd#p1500079 2 | 3 | root@raspberrypi:~# vcgencmd measure_volts usb_pd 4 | volt=1.7600V 5 | 6 | one ADC channel on the PMIC is routed to one CC line, and can read the center of the voltage-divider, if the cable is "not flipped" 7 | 8 | 9 | vcgencmd measure_volts ain1 10 | the 2nd ADC on the PMIC, usually tied to gnd 11 | 12 | 13 | for src in altscb arm cam0 cam1 ckl108 clk27 clk54 core debug0 debug1 dft dpi dsi0 dsi0esc dsi1 dsi1esc emmc emmc2 genet125 genet250 gisb gpclk0 gpclk1 h264 hevc isp m2mc otp pcm pixel plla pllb pllc plld pllh pulse pwm smi tectl testmux tsens uart usb v3d vec wdog xpt; do echo -e "$src:\t$(vcgencmd measure_clock $src)" ; done 14 | measure various clocks 15 | 16 | vcgencmd measure_temp pmic 17 | measure PMIC temp sensor 18 | 19 | 20 | for src in altscb arm cam0 cam1 ckl108 clk27 clk54 core debug0 debug1 dft dpi dsi0 dsi0esc dsi1 dsi1esc emmc emmc2 genet125 genet250 gisb gpclk0 gpclk1 h264 hevc isp m2mc otp pcm pixel plla pllb pllc plld pllh pulse pwm smi tectl testmux tsens uart usb v3d vec wdog xpt; do echo -e "$src:\t$(vcgencmd enable_clock $src)" ; done 21 | show if a clock is enabled or not 22 | 23 | 24 | vcgencmd measure_volts 2711 25 | 26 | -------------------------------------------------------------------------------- /docs/vce.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1731546#p1731546 2 | > Nope, vce is part of the control around the video codecs. 3 | 4 | 7f10_0000 vce data ram 5 | 7f11_0000 vce program ram 6 | 7f12_0000 vce core registers?? 7 | 7f14_0000 vce control registers? 8 | 9 | 10 | 2020-10-21 23:46:45 < clever> ive discovered that the raspberry pi also has a VCE peripheral, and its also known to use openmax, so i'm trying to see how similar the VCE's are 11 | 2020-10-21 23:47:59 < agd5f_> clever, not likely exactly the same. Our hardware team designed the VCE hardware 12 | 2020-10-21 23:48:34 < agd5f_> but general in the sense that there are only so many ways to do an H.264 encoder 13 | 14 | 15 | https://www.raspberrypi.org/forums/viewtopic.php?f=98&t=292730&p=1780435#p1780435 16 | > VideoCore describes a large number of multimedia blocks: ISP, JPEG (encode and decode), CSI2 receiver, display pipeline (Hardware Video Scalar, Pixel Valves, HDMI, DSI, DPI, and analogue TV encoders), V3D, video encode/decode accelerator, and Vector Processing Unit (VPU) to name a few. 17 | > H264 encode actually uses a number of sub-blocks: Motion Estimation, Prediction, Quantisation, and entropy coding (CABAC or CAVLC). 18 | > The VCE is a small processor to assist the video codec hardware blocks. 19 | 20 | -------------------------------------------------------------------------------- /firmware/panic.c: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Panic routine. 17 | 18 | =============================================================================*/ 19 | 20 | #include 21 | 22 | #include 23 | 24 | #if defined(__VIDEOCORE4__) 25 | #include 26 | #else 27 | #include 28 | #endif 29 | 30 | #include 31 | 32 | #undef panic 33 | 34 | void panic(const char* fmt, ...) { 35 | printf("panic(): "); 36 | 37 | va_list arp; 38 | 39 | va_start(arp, fmt); 40 | vprintf(fmt, arp); 41 | va_end(arp); 42 | 43 | putchar('\n'); 44 | 45 | hang_cpu(); 46 | } 47 | -------------------------------------------------------------------------------- /docs/vcdbg.txt: -------------------------------------------------------------------------------- 1 | https://github.com/raspberrypi/firmware/issues/377#issuecomment-84022356 2 | > vcdbg doesn't need to talk to VC for most of the commands. It opens VC's memory and extracts as much as it can, but does rely on finding some symbols from memory. 3 | 4 | vcdbg log msg 5 | vcdbg log assert 6 | `vcdbg tx -v` requires a non-stripped ELF, which the rpi foundation doesnt release 7 | https://www.raspberrypi.org/forums/viewtopic.php?p=1875343#p1875343 8 | > "vcdbg log assert" needs to have "start_debug=1" in config.txt to report anything. 9 | 10 | 11 | 12 | root@raspberrypi:~# vcdbg dumpstate 2>/dev/null 13 | 14 | 15 | https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=195178&start=100 16 | > What are the comparative loadings on the 2 VPU cores? "sudo vcdbg hist gnuplot" should give you two files called task.gpt and task.gpt, and "gnuplot task.gpt" should then display the three graphs of VPU0, VPU1, and combined. 17 | 18 | `vcdbg hist gnuplot` shows VPU usage?? 19 | 20 | > Got the static vcdbg from pelwell's link: 21 | > https://github.com/raspberrypi/Raspberry-Pi-OS-64bit/issues/67#issuecomment-653209729 22 | a static vcdbg! 23 | 24 | 25 | https://www.raspberrypi.org/forums/viewtopic.php?p=1827424#p1827424 26 | > There is an alternative implementation of part of vcdbg that you can try: https://git.venev.name/hristo/rpi-vc-log 27 | 28 | -------------------------------------------------------------------------------- /hs-gpio/hs-gpio.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | -- Initial package description 'hs-gpio.cabal' generated by 'cabal init'. 3 | -- For further documentation, see http://haskell.org/cabal/users-guide/ 4 | 5 | name: hs-gpio 6 | version: 0.1.0.0 7 | -- synopsis: 8 | -- description: 9 | -- bug-reports: 10 | author: Michael Bishop 11 | maintainer: cleverca22@gmail.com 12 | -- copyright: 13 | -- category: 14 | build-type: Simple 15 | 16 | executable hs-gpio 17 | main-is: Main.hs 18 | other-modules: AltModeViewer 19 | , FileChooser 20 | , GPIO 21 | , MainMenu 22 | , PlayWithDither 23 | , PromptString 24 | , Types 25 | -- other-extensions: 26 | build-depends: base 27 | , brick 28 | --, HPi 29 | , unix 30 | , formatting 31 | , vty 32 | , async 33 | , vector 34 | , directory 35 | , mtl 36 | --, prometheus 37 | -- hs-source-dirs: 38 | default-language: Haskell2010 39 | C-sources: cbits/helper.c 40 | ghc-options: -threaded -Wall 41 | -------------------------------------------------------------------------------- /common/udelay.c: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Simple timer based delay routine. 17 | 18 | =============================================================================*/ 19 | 20 | #include 21 | #include 22 | 23 | // not sure what controls the rate 24 | // but i have confirmed that ST_CLO counts micro-seconds 25 | // calling udelay(10 * 1000 * 1000) results in a stall of ~10 seconds 26 | // this is true for both vpu and arm 27 | void udelay(uint32_t t) { 28 | uint32_t tv = ST_CLO; 29 | for (;;) { 30 | /* nop still takes a cycle i think? */ 31 | __asm__ __volatile__ ("nop" :::); 32 | if ((ST_CLO - tv) > t) 33 | return; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/rpi4-gpio-mux.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | sdhost [label="SDHOST\n0x7e202000\nSD0_x"] 3 | sdhci [label="SDHCI\n0x7e300000\nSD1_x"] 4 | EMMC2 [label="EMMC2\n0x7e340000"] 5 | genet 6 | 7 | sd_bank0 -> GPIO22_27 8 | sd_bank1 -> GPIO34_43 9 | sd_bank2 -> GPIO48_53 10 | 11 | sdhost -> sd_bank0 12 | sdhost -> sd_bank2 13 | 14 | PL011 -> GPIO30_33 15 | 16 | EMMC2 -> sdmux [color=green,dir=both] 17 | 18 | sdhci -> sd_bank0 19 | sdhci -> sd_bank1 [color=green,dir=both] 20 | sdhci -> sd_bank2 21 | sdhci -> sdmux [color=red,dir=both] 22 | 23 | genet -> ethernetmux [dir=both] 24 | genet -> GPIO28_29 [dir=both] 25 | ethernetmux -> GPIO46_57 [label="RGMII",dir=both] 26 | 27 | sdmux -> uSD [dir=both] 28 | 29 | uSD [label="uSD slot\nnot on gpio array"] 30 | sd_bank1 [label="sd_bank1\n8bit capable"] 31 | 32 | SPI2 -> GPIO40_45 [label="40-45",color=red,dir=both] 33 | PWM1 -> GPIO40_45 [label="40,41",color=green] 34 | 35 | GPIO28_29 -> gigabit_phy [label="MDIO",dir=both] 36 | GPIO30_33 -> bluetooth 37 | GPIO34_43 -> wifi [label="34-39\n4bit mode"] 38 | GPIO40_45 -> analog_audio [label="40,41",color=green] 39 | GPIO40_45 -> status_led [label="42",color=green] 40 | GPIO40_45 -> camera [label="44,45",color=green,dir=both] 41 | GPIO40_45 -> eeprom [label="40-43",color=red,dir=both] 42 | GPIO46_57 -> gigabit_phy [label="RGMII",dir=both] 43 | } 44 | -------------------------------------------------------------------------------- /firmware/BCM2708PlatformStartup.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * VideoCore4_Drivers 3 | * Copyright (c) 2017 Kristina Brooks 4 | * 5 | * BCM2708 power management driver. 6 | */ 7 | 8 | #include 9 | #include 10 | #include "BCM2708PlatformStartup.h" 11 | #include 12 | 13 | BCM2708ArmControl gArmControl {}; 14 | 15 | static IODevice* startDeviceByTag(uint32_t tag) { 16 | IODevice* dev = IODevice::findByTag(tag); 17 | 18 | if (!dev) { 19 | panic("unable to find device with tag 0x%lX in the registry", tag); 20 | } 21 | 22 | dev->start(); 23 | return dev; 24 | } 25 | 26 | void PEStartPlatform(struct OtpInfo *info) { 27 | if (true) { 28 | IODevice* imagePm = PowerManagementDomain::getDeviceForDomain(kCprPowerDomainImage); 29 | assert(imagePm); 30 | IODevice* usbPm = PowerManagementDomain::getDeviceForDomain(kCprPowerDomainUSB); 31 | assert(usbPm); 32 | 33 | /* 34 | * All devices in the IMAGE domain have to be disabled before 35 | * starting the domain itself. 36 | */ 37 | usbPm->stop(); 38 | /* Bring up IMAGE power domain */ 39 | imagePm->start(); 40 | /* Now we can re-enable USB power domain */ 41 | usbPm->start(); 42 | 43 | /* Start USB PHY */ 44 | startDeviceByTag('USBP'); 45 | } 46 | 47 | /* Start ARM */ 48 | gArmControl.start(info); 49 | } 50 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/rnghw.h: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (c) 2007 Broadcom Europe Limited. All rights reserved. 3 | 4 | Project : BCM2707 5 | Module : RNG hardware header 6 | File : $RCSfile: rnghw.h,v $ 7 | Revision : $Revision: 1.2 $ 8 | 9 | FILE DESCRIPTION 10 | Definition of bits within RNG hardware registers. 11 | =============================================================================*/ 12 | 13 | 14 | 15 | #ifndef RNGHW_H 16 | #define RNGHW_H 17 | 18 | #define RNG_READFIELD(_w,_f) (((unsigned long)(_w) / _f) & (_f##_MASK)) 19 | 20 | enum 21 | { 22 | RNG_CTRL_RBG_2X = (1 << 1), 23 | RNG_CTRL_RBG_EN = (1 << 0), 24 | 25 | RNG_STATUS_WARM_CNT = (1 << 0), 26 | RNG_STATUS_WARM_CNT_MASK = 0xfffff, 27 | RNG_STATUS_VAL = (1 << 24), 28 | RNG_STATUS_VAL_MASK = 0xff, 29 | 30 | RNG_FF_THRESHOLD_MAX = 0x04, 31 | 32 | // BCM2707_B0: 33 | // RNG interrupt no longer uses Crypto local interrupt register 34 | // It is connected to interrupt bit 52 : ISRC1_0 bit 52-32=20 (0x0100000) 35 | // Mask has 6 IRQ/reg => floor(52/8)=6 Bits = 16:19 36 | 37 | RNG_INT_MASK_ENABLE = (1 << 16), 38 | RNG_INT_MASK_DISABLE = (0 << 16), 39 | 40 | RNG_SIMCTRL_DEBUG = (1 << 0), 41 | RNG_SIMCTRL_SECURE = (1 << 1) 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /docs/genet.md: -------------------------------------------------------------------------------- 1 | register | offset 2 | --- | --- 3 | `SYS_REV_CTRL` | `0x00` 4 | 5 | ## `SYS_REV_CTRL` register 6 | contains the major version# for the genet controller 7 | 8 | the bcm2711 uses genet version 5, which is what this documents 9 | 10 | bits | usage 11 | -----|------ 12 | 24:27 | major version#, not a simple int, refer to linux src 13 | 14 | 15 | ## dma descriptors 16 | 17 | the hw rx and tx rings are arrays of 256 elements each of: 18 | ``` 19 | struct { 20 | uint32_t length_status; 21 | uint32_t addr_lo; 22 | uint32_t addr_hi; 23 | } 24 | ``` 25 | beware, other genet versions may have only 32bit addressing, and lack the `addr_hi` field 26 | 27 | on genet 5, the rx ring begins at offset `0x2000` and the tx ring at offset `0x4000` 28 | 29 | ## dma length+status field 30 | 31 | 32 | rx only flags 33 | bits | usage 34 | ------|----- 35 | 0 | `RX_OV` 36 | 1 | `RX_CRC_ERROR` 37 | 2 | `RX_RXER` 38 | 3 | `RX_NO` 39 | 4 | `RX_LG` 40 | 5 | `RX_MULT` 41 | 6 | `RX_BRDCAST` 42 | 7:11 | `RX_FI` 43 | 12 | `RX_CHK_V12` 44 | 15 | `RX_CHK_V3PLUS` 45 | 46 | tx only flags 47 | bits | usage 48 | ------|----- 49 | 4 | `TX_DO_CSUM` 50 | 5 | `TX_OW_CRC` 51 | 6 | `TX_APPEND_CRC` 52 | 8 | `TX_UNDERRUN` 53 | 54 | common flags 55 | bits | usage 56 | ------|----- 57 | 12 | `WRAP` 58 | 13 | `SOP` 59 | 14 | `EOP` 60 | 15 | `OWN` 61 | 16:27 | the length of the packet 62 | -------------------------------------------------------------------------------- /docs/isp.txt: -------------------------------------------------------------------------------- 1 | https://www.raspberrypi.org/forums/viewtopic.php?p=1730991#p1730991 2 | > > ah, so that part would still be waiting on a proper ISP driver in linux 3 | > Broadcom IP - there won't be a native Linux driver for it. 4 | 5 | https://android.googlesource.com/kernel/bcm/+/android-bcm-tetra-3.10-kitkat-wear/drivers/char/broadcom/isp2/isp2.c 6 | > You've got a very remote shot with https://android.googlesource.com/kernel ... sp2/isp2.c but its largely just allowing userspace to map the registers to be poked and handling the interrupts. 7 | > There are a couple of revisions of the isp hardware, and I don't recall if Java and Rhea had the cut-down versions or the full ones. 8 | 9 | 10 | https://www.raspberrypi.org/forums/viewtopic.php?p=1765429#p1765429 11 | > We normally reckon on around 130MPix/s through the ISP. 1280x800@120fps is 122.8MPix/s, and you're trying to do that twice! 12 | > I don't think the ISP has been accurately benchmarked for a long time. Theory is it can handle one pixel per clock cycle, but that's limited both sides of any scaling. It also works in tiles with overlaps, so full throughput depends on exactly how many tiles are required. 13 | 14 | 15 | https://www.raspberrypi.org/forums/viewtopic.php?p=1832607#p1832607 16 | details on which v4l nodes do what 17 | 18 | https://www.raspberrypi.org/forums/viewtopic.php?p=1832607#p1832607 19 | > media-ctl --print-dot /dev/media2 > isp.dot 20 | > dot -Tpng isp.dot > isp.png 21 | -------------------------------------------------------------------------------- /dts/bcm2835-common.dtsi: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | 3 | /* This include file covers the common peripherals and configuration between 4 | * bcm2835, bcm2836 and bcm2837 implementations. 5 | */ 6 | 7 | / { 8 | soc { 9 | timer@7e003000 { 10 | compatible = "brcm,bcm2835-system-timer"; 11 | reg = <0x7e003000 0x1000>; 12 | interrupts = <1 0>, <1 1>, <1 2>, <1 3>; 13 | /* This could be a reference to BCM2835_CLOCK_TIMER, 14 | * but we don't have the driver using the common clock 15 | * support yet. 16 | */ 17 | clock-frequency = <1000000>; 18 | }; 19 | 20 | intc: interrupt-controller@7e00b200 { 21 | compatible = "brcm,bcm2835-armctrl-ic"; 22 | reg = <0x7e00b200 0x200>; 23 | interrupt-controller; 24 | #interrupt-cells = <2>; 25 | }; 26 | 27 | thermal: thermal@7e212000 { 28 | compatible = "brcm,bcm2835-thermal"; 29 | reg = <0x7e212000 0x8>; 30 | clocks = <&clocks BCM2835_CLOCK_TSENS>; 31 | #thermal-sensor-cells = <0>; 32 | status = "disabled"; 33 | }; 34 | 35 | v3d: v3d@7ec00000 { 36 | compatible = "brcm,bcm2835-v3d"; 37 | reg = <0x7ec00000 0x1000>; 38 | interrupts = <1 10>; 39 | }; 40 | }; 41 | }; 42 | 43 | &gpio { 44 | i2c_slave_gpio18: i2c_slave_gpio18 { 45 | brcm,pins = <18 19 20 21>; 46 | brcm,function = ; 47 | }; 48 | 49 | jtag_gpio4: jtag_gpio4 { 50 | brcm,pins = <4 5 6 12 13>; 51 | brcm,function = ; 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /arm_chainloader/chainloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "arm-defs.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | static inline void __attribute__((noreturn)) _hang_cpu() { 14 | __asm__ __volatile__ ("wfi\n"); 15 | 16 | /* in case the above fails */ 17 | for (;;) { 18 | __asm__ __volatile__ ("nop\nnop\nnop\nnop\nnop\nnop"); 19 | __asm__ __volatile__ ("wfi\n"); 20 | } 21 | } 22 | 23 | #define STATIC_INIT_PRIORITY(x) __attribute__((init_priority(x))) 24 | 25 | #define STATIC_CPRMAN_DRIVER STATIC_INIT_PRIORITY(101) 26 | #define STATIC_DRIVER STATIC_INIT_PRIORITY(200) 27 | #define STATIC_FILESYSTEM STATIC_INIT_PRIORITY(300) 28 | #define STATIC_APP STATIC_INIT_PRIORITY(600) 29 | 30 | #define mfence() __sync_synchronize() 31 | 32 | #define NBBY 8 33 | 34 | #define __BIT(__n) \ 35 | (((uintmax_t)(__n) >= NBBY * sizeof(uintmax_t)) ? 0 : \ 36 | ((uintmax_t)1 << (uintmax_t)((__n) & (NBBY * sizeof(uintmax_t) - 1)))) 37 | 38 | static inline uint32_t arm_get_cpsr() { 39 | uint32_t r; 40 | __asm__ volatile("mrs %0, cpsr\n" : "=r" (r) :: "memory"); 41 | return r; 42 | } 43 | 44 | static inline uint32_t arm_get_midr() { 45 | uint32_t r; 46 | __asm__("mrc p15, 0, %0, c0, c0, 0" : "=r"(r)); 47 | return r; 48 | } 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /netboot.nix: -------------------------------------------------------------------------------- 1 | { 2 | networking = { 3 | #useNetworkd = true; 4 | }; 5 | #systemd.network.enable = true; 6 | #systemd.network.links.eth0.enable = true; 7 | #systemd.network.networks.eth0.networkConfig.KeepConfiguration = "dhcp"; 8 | boot.initrd = { 9 | extraUtilsCommands = '' 10 | copy_bin_and_libs ${(import pkgs.path { system = "armv7l-linux"; overlays = [ overlay2 ]; }).openiscsi}/bin/iscsistart 11 | copy_bin_and_libs ${pkgs.strace}/bin/strace $out/bin/strace 12 | cp -v ${pkgs.glibc}/lib/libpthread* $out/lib/ 13 | cp ${pkgs.stdenv.cc.cc}/armv7l-unknown-linux-gnueabihf/lib/libgcc_s.so $out/lib/ -v 14 | ''; 15 | extraUtilsCommandsTest = '' 16 | strace --version 17 | ''; 18 | network = { 19 | enable = true; 20 | postCommands = '' 21 | iscsistart -t iqn.2020-01.com.angeldsis:rpi-image1.img -a 192.168.2.61 -i iqn.2015-09.com.example:3255a7223b2 -g 0 22 | ''; 23 | ssh = { 24 | enable = true; 25 | authorizedKeys = [ 26 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC34wZQFEOGkA5b0Z6maE3aKy/ix1MiK1D0Qmg4E9skAA57yKtWYzjA23r5OCF4Nhlj1CuYd6P1sEI/fMnxf+KkqqgW3ZoZ0+pQu4Bd8Ymi3OkkQX9kiq2coD3AFI6JytC6uBi6FaZQT5fG59DbXhxO5YpZlym8ps1obyCBX0hyKntD18RgHNaNM+jkQOhQ5OoxKsBEobxQOEdjIowl2QeEHb99n45sFr53NFqk3UCz0Y7ZMf1hSFQPuuEC/wExzBBJ1Wl7E1LlNA4p9O3qJUSadGZS4e5nSLqMnbQWv2icQS/7J8IwY0M8r1MsL8mdnlXHUofPlG1r4mtovQ2myzOx clever@nixos" 27 | ]; 28 | }; 29 | }; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/rng.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define RNG_BASE 0x7e104000 3 | #define RNG_APB_ID 0x20726e67 4 | #define RNG_CTRL HW_REGISTER_RW( 0x7e104000 ) 5 | #define RNG_CTRL_MASK 0xffffffff 6 | #define RNG_CTRL_WIDTH 32 7 | #define RNG_STATUS HW_REGISTER_RW( 0x7e104004 ) 8 | #define RNG_STATUS_MASK 0xffffffff 9 | #define RNG_STATUS_WIDTH 32 10 | #define RNG_DATA HW_REGISTER_RW( 0x7e104008 ) 11 | #define RNG_DATA_MASK 0xffffffff 12 | #define RNG_DATA_WIDTH 32 13 | #define RNG_FF_THRESHOLD HW_REGISTER_RW( 0x7e10400c ) 14 | #define RNG_FF_THRESHOLD_MASK 0xffffffff 15 | #define RNG_FF_THRESHOLD_WIDTH 32 16 | #define RNG_INT_MASK HW_REGISTER_RW( 0x7e104010 ) 17 | #define RNG_INT_MASK_MASK 0xffffffff 18 | #define RNG_INT_MASK_WIDTH 32 19 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/cdp.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define CD_BASE 0x1820b000 3 | #define CD_APB_ID 0x43445000 4 | #define CD_CS HW_REGISTER_RW( 0x1820b000 ) 5 | #define CD_CS__MASK 0xffffffff 6 | #define CD_CS__WIDTH 32 7 | #define CD_CS__RESET 0000000000 8 | #define CD_CS__MSB 31 9 | #define CD_CS__LSB 0 10 | #define CD_PHYADJ HW_REGISTER_RW( 0x1820b004 ) 11 | #define CD_PHYADJ__MASK 0x0000ffff 12 | #define CD_PHYADJ__WIDTH 16 13 | #define CD_PHYADJ__MSB 15 14 | #define CD_PHYADJ__LSB 0 15 | #define CD_PHYDAT HW_REGISTER_RO( 0x1820b008 ) 16 | #define CD_PHYDAT__MASK 0xffffffff 17 | #define CD_PHYDAT__WIDTH 32 18 | #define CD_PHYDAT__MSB 31 19 | #define CD_PHYDAT__LSB 0 20 | -------------------------------------------------------------------------------- /common/IODevice.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static IODevice* g_DeviceRegistry[32] = { 0 }; 5 | static unsigned int g_NewDriverIndex = 0; 6 | 7 | IODevice::IODevice() { 8 | 9 | } 10 | 11 | void IODevice::_beforeInit() { 12 | tag = 0; 13 | deviceState = kIODeviceUninitialized; 14 | } 15 | 16 | void IODevice::_afterInit() { 17 | assert(driverName); 18 | if (tag) 19 | registerDriver(); 20 | } 21 | 22 | void IODevice::registerDriver() { 23 | g_DeviceRegistry[g_NewDriverIndex++] = this; 24 | IODriverLog("driver registered on platform IO plane"); 25 | } 26 | 27 | void IODevice::driverLog(const char* fnName, const char* fmt, ...) { 28 | va_list va; 29 | uint32_t clock_lo = ST_CLO; 30 | 31 | printf("%3ld.%06ld ", clock_lo / 1000000, clock_lo % 1000000); 32 | 33 | printf("%s::%s(): ", driverName, fnName); 34 | va_start(va, fmt); 35 | vprintf(fmt, va); 36 | va_end(va); 37 | printf("\n"); 38 | } 39 | 40 | IODevice* IODevice::findByTag(uint32_t tag) { 41 | for (unsigned int i = 0; i < (sizeof(g_DeviceRegistry) / sizeof(void*)); i++) { 42 | IODevice* dev = g_DeviceRegistry[i]; 43 | if (dev && dev->tag == tag) { 44 | return dev; 45 | } 46 | } 47 | 48 | return nullptr; 49 | } 50 | 51 | void IODevice::start() { 52 | deviceState = kIODeviceStarted; 53 | } 54 | 55 | void IODevice::stop() { 56 | deviceState = kIODeviceStopped; 57 | } 58 | 59 | void IODevice::init() { 60 | panic("IODevice objects have to override init()"); 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /arm64/start.s: -------------------------------------------------------------------------------- 1 | .section .text.start 2 | .global _start 3 | _start: 4 | mrs x0, mpidr_el1 5 | and x0, x0, #3 6 | cbz x0, _init 7 | 0: 8 | wfe 9 | b 0b 10 | .org 0x080 11 | b . 12 | .org 0x100 13 | b . 14 | .org 0x180 15 | b . 16 | .org 0x200 17 | mrs x0, CurrentEL 18 | mrs x1, ELR_EL3 19 | mrs x2, ESR_EL3 20 | bl handle_exception200 21 | b . 22 | .org 0x280 23 | b . 24 | .org 0x300 25 | b . 26 | .org 0x380 27 | b . 28 | .org 0x400 29 | b . 30 | .org 0x480 31 | b . 32 | .org 0x500 33 | b . 34 | .org 0x580 35 | b . 36 | .org 0x600 37 | b . 38 | .org 0x680 39 | b . 40 | .org 0x700 41 | b . 42 | .org 0x780 43 | b . 44 | 45 | .global smc_up 46 | smc_up: 47 | smc 0x1234 48 | b . 49 | 50 | _init: 51 | mrs x0, currentel 52 | mov x0, #0 53 | msr ELR_EL1, x0 54 | msr ESR_EL1, x0 55 | msr SPSR_EL1, x0 56 | 57 | msr ELR_EL2, x0 58 | msr ESR_EL2, x0 59 | msr SPSR_EL2, x0 60 | 61 | msr ELR_EL3, x0 62 | msr ESR_EL3, x0 63 | msr SPSR_EL3, x0 64 | 65 | mov x5, x0 66 | mov x6, x0 67 | mov x7, x0 68 | mov x8, x0 69 | ldr x0, =_fstack 70 | mov sp, x0 71 | 72 | bl main 73 | b stall 74 | 75 | stall: 76 | b . 77 | 78 | .global drop_privs 79 | drop_privs: 80 | msr ELR_EL3, x0 81 | msr SPSR_EL3, x1 82 | msr scr_el3, x2 83 | ldr x0, =_fstack 84 | msr SP_EL2, x0 85 | eret 86 | 87 | .global reentry 88 | reentry: 89 | mov x0, #0 90 | msr VBAR_EL2, x0 91 | // ldr x0, =_fstack 92 | // mov sp, x0 93 | bl el2_main 94 | b . 95 | -------------------------------------------------------------------------------- /common/hexdump.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void safe_putchar(unsigned char c) { 6 | if ((c >= ' ') && (c <= '~')) { 7 | printf("%c", c); 8 | } else { 9 | printf("."); 10 | } 11 | } 12 | 13 | // realaddr must be 16 aligned 14 | // reads from realaddr, but claims to be from reportaddr, to allow mmap usage 15 | // count must be a multiple of 16 bytes 16 | void hexdump_ram(volatile void *realaddr, uint32_t reportaddr, uint32_t count) { 17 | volatile uint32_t *buffer_start = reinterpret_cast(realaddr); 18 | for (uint32_t i = 0, fakeaddr = reportaddr; i < count; i += 16, fakeaddr += 16) { 19 | uint32_t fragment; 20 | printf("0x%08lx ", fakeaddr); 21 | for (int j=0; j<4; j++) { 22 | fragment = buffer_start[((i/4)+j)]; 23 | uint8_t a,b,c,d; 24 | a = fragment & 0xff; 25 | b = (fragment >> 8) & 0xff; 26 | c = (fragment >> 16) & 0xff; 27 | d = (fragment >> 24) & 0xff; 28 | printf("%02x %02x %02x %02x ", a,b,c,d); 29 | if (j == 1) printf(" "); 30 | } 31 | printf(" |"); 32 | for (int j=0; j<4; j++) { 33 | fragment = buffer_start[((i/4)+j)]; 34 | uint8_t a,b,c,d; 35 | a = fragment & 0xff; 36 | b = (fragment >> 8) & 0xff; 37 | c = (fragment >> 16) & 0xff; 38 | d = (fragment >> 24) & 0xff; 39 | safe_putchar(a); 40 | safe_putchar(b); 41 | safe_putchar(c); 42 | safe_putchar(d); 43 | } 44 | printf("|\n"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /firmware/vc4_include/pcb.h: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Process control block. 17 | 18 | =============================================================================*/ 19 | 20 | #pragma once 21 | 22 | #include 23 | 24 | typedef struct { 25 | uint32_t r23; 26 | uint32_t r22; 27 | uint32_t r21; 28 | uint32_t r20; 29 | uint32_t r19; 30 | uint32_t r18; 31 | uint32_t r17; 32 | uint32_t r16; 33 | uint32_t r15; 34 | uint32_t r14; 35 | uint32_t r13; 36 | uint32_t r12; 37 | uint32_t r11; 38 | uint32_t r10; 39 | uint32_t r9; 40 | uint32_t r8; 41 | uint32_t r7; 42 | uint32_t r6; 43 | 44 | uint32_t r5; 45 | uint32_t r4; 46 | uint32_t r3; 47 | uint32_t r2; 48 | uint32_t r1; 49 | uint32_t r0; 50 | 51 | uint32_t lr; 52 | 53 | uint32_t sr; 54 | uint32_t pc; 55 | } vc4_saved_state_t; 56 | -------------------------------------------------------------------------------- /tlsf/tlsf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Two Levels Segregate Fit memory allocator (TLSF) 3 | * Version 2.4.6 4 | * 5 | * Written by Miguel Masmano Tello 6 | * 7 | * Thanks to Ismael Ripoll for his suggestions and reviews 8 | * 9 | * Copyright (C) 2008, 2007, 2006, 2005, 2004 10 | * 11 | * This code is released using a dual license strategy: GPL/LGPL 12 | * You can choose the licence that better fits your requirements. 13 | * 14 | * Released under the terms of the GNU General Public License Version 2.0 15 | * Released under the terms of the GNU Lesser General Public License Version 2.1 16 | * 17 | */ 18 | 19 | #ifndef _TLSF_H_ 20 | #define _TLSF_H_ 21 | 22 | #include 23 | 24 | #define tlsf_malloc malloc 25 | #define tlsf_free free 26 | #define tlsf_realloc realloc 27 | #define tlsf_calloc calloc 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | extern size_t init_memory_pool(size_t, void *); 34 | extern size_t get_used_size(void *); 35 | extern size_t get_max_size(void *); 36 | extern void destroy_memory_pool(void *); 37 | extern size_t add_new_area(void *, size_t, void *); 38 | extern void *malloc_ex(size_t, void *); 39 | extern void free_ex(void *, void *); 40 | extern void *realloc_ex(void *, size_t, void *); 41 | extern void *calloc_ex(size_t, size_t, void *); 42 | 43 | extern void *tlsf_malloc(size_t size); 44 | extern void tlsf_free(void *ptr); 45 | extern void *tlsf_realloc(void *ptr, size_t size); 46 | extern void *tlsf_calloc(size_t nelem, size_t elem_size); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /docs/start4.txt: -------------------------------------------------------------------------------- 1 | .text.firmware_rev is a 16 byte section detailing what the start4.elf supports 2 | 3 | byte 0 bit 0 must be set for it to boot on cpuid 0x4000162, bcm2711C0? 4 | byte 0 bit 0&1 must be set, if some_flag1 bit 1 is present, both bits required to boot in usb-dev on a pi400 5 | byte 0 bit 2 must be set, if some_flag2 is non-zero 6 | byte 0 bit 3 must be set, if flag1 and flag2 are both non-zero 7 | byte 0 BIT4(0x10) USB-MSD, must be set for it to boot with usb mass-storage 8 | byte 0 BIT5(0x20) BCM-USB-MSD, must be set for it to boot with broadcom xhci mass storage 9 | byte 0 BIT7(0x80) netboot related 10 | byte 0 BIT8(0x100) NVME boot supported 11 | byte 0 BIT9(0x200) checked in beta-2021-07-06, secureboot/ramdisk related? 12 | byte 0 BIT10(0x400) checked in beta-2021-07-06, secureboot/ramdisk related? 13 | 14 | .text.bootloader_state is a 16 byte section 15 | 001f7550 42 53 54 41 00 00 00 00 00 00 00 00 00 00 00 00 |BSTA............| 16 | if the first 4 bytes contain this magic, then 0x40000 is put into the the uint32_t at offset 4 17 | 18 | the vaddr of every DT_LOAD must be above 32mb 19 | when filesize is less then memsize, the extra space is zero'd 20 | 21 | 0xc002_0000 length 0x400 gets zero'd before passing control 22 | something of length 0x1b8 gets copied to 0xc004_0000, its the `struct bootloader_state` 23 | 24 | return address will be pointing to a bkpr opcode 25 | 26 | 12mb max start4.elf size 27 | 28 | fixup data: 29 | bits 30 | 0-7, directly from fixup_record[0] 31 | 8-15, from fixup-record[1] 32 | 10-17, from fixup-record[2] 33 | overlay just or's together 34 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/block_device.hpp: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Block device. 17 | 18 | =============================================================================*/ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | void sdhost_init(); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #ifdef __cplusplus 30 | struct BlockDevice { 31 | unsigned int block_size; 32 | 33 | template 34 | inline bool read_block(uint32_t sector, T* dest_buffer, uint32_t count) { 35 | return read_block(sector, reinterpret_cast(dest_buffer), count); 36 | } 37 | 38 | inline unsigned int get_block_size() { 39 | return block_size; 40 | } 41 | 42 | virtual bool read_block(uint32_t sector, uint32_t* buf, uint32_t count) = 0; 43 | 44 | /* called to stop the block device */ 45 | virtual void stop() {} 46 | }; 47 | 48 | extern BlockDevice* get_sdhost_device(); 49 | #endif 50 | -------------------------------------------------------------------------------- /firmware/start.S: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Entry. 17 | 18 | A small explanation. The ROM loads bootcode.bin at 0x80000000 and jumps to 19 | 0x80000200. This region corresponds to L1/L2 cached IO and cache is never 20 | evicted as long as we don't touch memory above that. This gives us 128KB 21 | of memory at startup. 22 | 23 | Exception names are from the public release from: 24 | brcm_usrlib\dag\vmcsx\vcfw\rtos\none\rtos_none.c 25 | 26 | =============================================================================*/ 27 | 28 | /* main entry point */ 29 | .section .text.start 30 | .globl _start 31 | .align 2 32 | _start: 33 | mov sp, _fstack 34 | 35 | #if 0 36 | stm r0, (--sp) // dummy 37 | stm r0, (--sp) // values 38 | stm lr, (--sp) 39 | stm r0-r5, (--sp) 40 | stm r6-r15, (--sp) 41 | stm r16-r23, (--sp) 42 | mov r2, sp 43 | #else 44 | mov r2, 0 45 | #endif 46 | 47 | version r0 48 | lea r1, _start 49 | /* jump to C code */ 50 | bl _main 51 | b . 52 | -------------------------------------------------------------------------------- /hs-gpio/GPIO.hs: -------------------------------------------------------------------------------- 1 | module GPIO where 2 | 3 | import Data.Bits 4 | import Data.Word 5 | import Foreign.Storable 6 | import GHC.Ptr 7 | 8 | data GPIO 9 | data RPI 10 | data HVS 11 | 12 | toGPIO :: Ptr RPI -> Ptr GPIO 13 | toGPIO p = (castPtr p) `plusPtr` 0x200000 14 | 15 | toHVS :: Ptr RPI -> Ptr HVS 16 | toHVS p = (castPtr p) `plusPtr` 0x400000 17 | 18 | data AltMode = AltIn | AltOut | Alt0 | Alt1 | Alt2 | Alt3 | Alt4 | Alt5 deriving Show 19 | 20 | newtype Pin = Pin Int deriving Show 21 | 22 | instance Num Pin where 23 | fromInteger p = Pin $ fromIntegral p 24 | 25 | instance Enum Pin where 26 | succ (Pin p) = Pin $ succ p 27 | fromEnum (Pin p) = p 28 | toEnum p = Pin p 29 | 30 | instance Bounded Pin where 31 | minBound = Pin 0 32 | maxBound = Pin 59 33 | 34 | rawModeToAltMode :: Word32 -> AltMode 35 | rawModeToAltMode 0 = AltIn 36 | rawModeToAltMode 1 = AltOut 37 | rawModeToAltMode 2 = Alt5 38 | rawModeToAltMode 3 = Alt4 39 | rawModeToAltMode 4 = Alt0 40 | rawModeToAltMode 5 = Alt1 41 | rawModeToAltMode 6 = Alt2 42 | rawModeToAltMode 7 = Alt3 43 | 44 | getPinAltMode :: Ptr GPIO -> Pin -> IO AltMode 45 | getPinAltMode addr (Pin pin) = do 46 | let (bank, row) = pin `divMod` 10 47 | reg <- peek (addr `plusPtr` (4 * bank)) 48 | pure $ rawModeToAltMode $ (shiftR reg (3 * row)) .&. 7 49 | 50 | getPinStates :: Ptr GPIO -> IO [(Pin, AltMode)] 51 | getPinStates addr = do 52 | let 53 | allPins = [ minBound .. maxBound ] 54 | f :: Pin -> IO (Pin, AltMode) 55 | f pin = do 56 | mode <- getPinAltMode addr pin 57 | --fprint ("pin "%d%" is in mode "%shown%"\n") (fromEnum pin) mode 58 | pure (pin, mode) 59 | mapM f allPins 60 | -------------------------------------------------------------------------------- /common/eeprom.txt: -------------------------------------------------------------------------------- 1 | https://github.com/raspberrypi/rpi-eeprom/pull/244/files 2 | # The last 4KB of the EEPROM image is reserved for internal use by the 3 | # bootloader and may be overwritten during the update process. 4 | 5 | .sig files now contain: 6 | ``` 7 | ${sha256} 8 | ts: ${timestamp} 9 | ``` 10 | the timestamp is a unix timestamp, base10 11 | # During an self-update mode the bootloader examines the update timestamp 12 | # and will only update itself if it is newer than than the current update timestamp 13 | 14 | 15 | https://github.com/raspberrypi/rpi-eeprom/pull/246 16 | # On Pi 4B 1.4 (8GB) initialise SDRAM whilst waiting for the USB port power off time. This makes booting slightly faster. 17 | # Skip rendering of the diagnostics screen for HDMI_DELAY seconds (default 5). This means that for SD-card and USB MSD flash boot devices the diagnostics screen will not be visible. 18 | # Fix issue where boot would stop if partition type 0x83 was encountered before the first FAT partition. 19 | # SELF_UPDATE mode (Network, USB MSD boot) now reads the timestamp information in pieeprom.sig created by rpi-eeprom-update to see if the updated is newer than the current 'update-timestamp'. If not, the update is skipped to avoid stale updates on network or USB disks being installed by accident. 20 | # recovery.bin updates (from the SD card) do not check the timestamp because recovery.bin renames itself once the update is completed. However, it still writes the update-timestamp to the EEPROM. 21 | # Add support for the 'tryboot' feature that enables operating systems to implement a fallback mechanism if an OS upgrade fails. This works with all bootable media types but requires updated firmware and OS software. 22 | 23 | -------------------------------------------------------------------------------- /firmware/start.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * based heavily on https://github.com/ptesarik/vc4boot 3 | */ 4 | 5 | OUTPUT_FORMAT("elf32-vc4", "elf32-vc4", "elf32-vc4") 6 | OUTPUT_ARCH(vc4) 7 | ENTRY(_start) 8 | GROUP(-lgloss -lc -lteststub -lgcc) 9 | 10 | MEMORY { 11 | /* in the C alias, direct uncached 12 | */ 13 | ram (rwx) : ORIGIN = 0xc0000000 + 2M, LENGTH = 20M 14 | } 15 | SECTIONS { 16 | .text : ALIGN(32) { 17 | PROVIDE(_start = .); 18 | . = ALIGN(4); 19 | *(.text .stub .text.* .gnu.linkonce.t.*) 20 | *(.gnu.warning) 21 | KEEP (*(.init)) 22 | KEEP (*(.fini)) 23 | KEEP (*(.jcr)) 24 | _etext = .; 25 | } >ram =0 26 | 27 | .rodata : { 28 | . = ALIGN(4); 29 | _frodata = .; 30 | *(.rodata .rodata.* .gnu.linkonce.r.*) 31 | *(.rodata1) 32 | _erodata = .; 33 | } >ram 34 | 35 | .init_array : { 36 | PROVIDE (__init_array_start = .); 37 | *(.init_array) 38 | *(.init_array.*) 39 | *(.ctors) 40 | *(.ctors.*) 41 | __init_array_end = .; 42 | } >ram 43 | 44 | .data : { 45 | . = ALIGN(4); 46 | _fdata = .; 47 | *(.data .data.* .gnu.linkonce.d.*) 48 | *(.data1) 49 | SORT(CONSTRUCTORS) 50 | *(.sdata .sdata.* .gnu.linkonce.s.*) 51 | _edata = .; 52 | } >ram 53 | 54 | .bss : { 55 | . = ALIGN(4); 56 | _fbss = .; 57 | *(.dynsbss) 58 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 59 | *(.scommon) 60 | *(.dynbss) 61 | *(.bss .bss.* .gnu.linkonce.b.*) 62 | *(COMMON) 63 | . = ALIGN(4); 64 | _ebss = .; 65 | _end = .; 66 | PROVIDE (end = .); 67 | } >ram 68 | 69 | /* First location in stack is highest address in RAM */ 70 | PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4); 71 | } 72 | -------------------------------------------------------------------------------- /arm_chainloader/drivers/mailbox.cc: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Mailbox driver. 17 | 18 | =============================================================================*/ 19 | 20 | #include "mailbox.hpp" 21 | #include 22 | #include 23 | 24 | #define logf(fmt, ...) printf("[MBOX:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); 25 | 26 | template 27 | static bool wait_for_mask(T& reg, uint32_t mask, bool is_set, int timeout) { 28 | while ((reg & mask) == (is_set ? 0 : mask)) { 29 | if (timeout == 0) 30 | return false; 31 | timeout--; 32 | udelay(1); 33 | } 34 | 35 | return true; 36 | } 37 | 38 | Bcm2708Mailbox::Bcm2708Mailbox() { 39 | 40 | } 41 | 42 | bool Bcm2708Mailbox::write_word(uint32_t data, int timeout) { 43 | if (!wait_for_mask(ARM_0_MAIL1_STA, ARM_MS_FULL, false, timeout)) { 44 | logf("mailbox write timed out after %dus (STA=0x%lX)\n", timeout, ARM_0_MAIL1_STA); 45 | return false; 46 | } 47 | 48 | ARM_0_MAIL1_WRT = data; 49 | return true; 50 | } 51 | 52 | Bcm2708Mailbox STATIC_DRIVER g_Mailbox {}; 53 | -------------------------------------------------------------------------------- /docs/vec.txt: -------------------------------------------------------------------------------- 1 | root@raspberrypi:~# cat /boot/config.txt 2 | dtoverlay=vc4-kms-v3d 3 | root@raspberrypi:~# cat /proc/cpuinfo 4 | model name : ARMv6-compatible processor rev 7 (v6l) 5 | Revision : 100000e 6 | Serial : 00000000230aad04 7 | Model : Raspberry Pi Model B Rev 2 8 | 9 | root@raspberrypi:~# cat /sys/kernel/debug/dri/0/vec_regs 10 | VEC_WSE_CONTROL = 0x00001614 11 | VEC_WSE_WSS_DATA = 0x00000800 12 | VEC_WSE_VPS_DATA1 = 0x00000010 13 | VEC_WSE_VPS_CONTROL = 0x00000780 14 | VEC_REVID = 0x00002708 15 | VEC_CONFIG0 = 0x00000040 16 | VEC_SCHPH = 0x0000ff28 17 | VEC_CLMP0_START = 0x000000ac 18 | VEC_CLMP0_END = 0x000000ec 19 | VEC_FREQ3_2 = 0x000029c7 20 | VEC_FREQ1_0 = 0x00001c72 21 | VEC_CONFIG1 = 0x00001c00 22 | VEC_CONFIG2 = 0x00000060 23 | VEC_INTERRUPT_CONTROL = 0x00000003 24 | VEC_INTERRUPT_STATUS = 0x00000003 25 | VEC_FCW_SECAM_B = 0x284bda13 26 | VEC_SECAM_GAIN_VAL = 0x44824224 27 | VEC_CONFIG3 = 0x00000000 28 | VEC_STATUS0 = 0x00000003 29 | VEC_MASK0 = 0x00000000 30 | VEC_CFG = 0x0000000a 31 | VEC_DAC_TEST = 0x00000000 32 | VEC_DAC_CONFIG = 0x460c000c 33 | VEC_DAC_MISC = 0x00000101 34 | root@raspberrypi:~# tvservice -s 35 | state 0x40001 [NTSC 4:3], 720x480 @ 60.00Hz, interlaced 36 | 37 | 38 | https://www.raspberrypi.org/forums/viewtopic.php?p=1728650 39 | > enable_tvout limits the core clock to 432 (from default of 500) as the vec hardware needs 108MHz and shares a PLL channel. 40 | 41 | 42 | https://www.raspberrypi.org/forums/viewtopic.php?f=67&t=271568 43 | > Understanding custom frequency setting in VEC 44 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/tectl_a0.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define TE_BASE 0x7e20e000 3 | #define TE_APB_ID 0x00746563 4 | #define TE_0C HW_REGISTER_RW( 0x7e20e000 ) 5 | #define TE_0C_MASK 0xffffffff 6 | #define TE_0C_WIDTH 32 7 | #define TE_0VSWIDTH HW_REGISTER_RW( 0x7e20e004 ) 8 | #define TE_0VSWIDTH_MASK 0xffffffff 9 | #define TE_0VSWIDTH_WIDTH 32 10 | #define TE_1C HW_REGISTER_RW( 0x7e20e008 ) 11 | #define TE_1C_MASK 0xffffffff 12 | #define TE_1C_WIDTH 32 13 | #define TE_1VSWIDTH HW_REGISTER_RW( 0x7e20e00c ) 14 | #define TE_1VSWIDTH_MASK 0xffffffff 15 | #define TE_1VSWIDTH_WIDTH 32 16 | #define TE_2C HW_REGISTER_RW( 0x7e20e010 ) 17 | #define TE_2C_MASK 0xffffffff 18 | #define TE_2C_WIDTH 32 19 | #define TE_2VSWIDTH HW_REGISTER_RW( 0x7e20e014 ) 20 | #define TE_2VSWIDTH_MASK 0xffffffff 21 | #define TE_2VSWIDTH_WIDTH 32 22 | -------------------------------------------------------------------------------- /docs/arm-arch.txt: -------------------------------------------------------------------------------- 1 | taken from https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/ 2 | 3 | pi1: -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s 4 | pi2: -mfpu=neon-vfpv4 -march=armv7-a -mtune=cortex-a7 5 | pi3: -mfpu=crypto-neon-fp-armv8 -march=armv8-a+crc -mcpu=cortex-a53 6 | pi4: -mfpu=crypto-neon-fp-armv8 -march=armv8-a+crc -mcpu=cortex-a72 7 | 8 | gathered from pi's i own: 9 | 10 | pi0/pi1: 11 | SoC serial# 0x230aad04 12 | HW revision: 0x0000000e 13 | MIDR: 0x410FB767 14 | armv6 cache type: 0x1d152152 15 | L1i: words: 2, assoc: 2, size: 5, size2: 0 16 | L1d: words: 2, assoc: 2, size: 5, size2: 0 17 | S: 1 18 | CType: 14 19 | 8 words per line 20 | 4 way associative 21 | 16kb each 22 | 23 | pi2: 24 | SoC serial# 0x1077df95 25 | HW revision: 0x00a21041 26 | Type: 4 27 | Rev: 1 28 | Proc: 1 29 | Manufacturer: 2 30 | Ram: 2 31 | MIDR: 0x410FC075 32 | name size encoding WT WB RA WA Sets Assoc LineSize 33 | L1d 32 KB 0x700fe01a 0 1 1 1 0x7f 0x3 0x2(64 bytes) 34 | L1i 32 KB 0x203fe009 0 0 1 0 0x1ff 0x1 0x1(32 bytes) 35 | L2 512 KB 0x707fe03a 0 1 1 1 0x3ff 0x7 0x2(64 bytes) 36 | 37 | 38 | pi3: 39 | SoC serial# 0x9080d9b6 40 | HW revision: 0x00a22082 41 | Type: 8 42 | Rev: 2 43 | Proc: 2 44 | Manufacturer: 2 45 | Ram: 2 46 | MIDR: 0x410fd034 47 | name size encoding WT WB RA WA Sets Assoc LineSize 48 | L1d 32 KB 0x700fe01a 0 1 1 1 0x7f 0x3 0x2(64 bytes) 49 | L1i 32 KB 0x201fe00a 0 0 1 0 0xff 0x1 0x2(64 bytes) 50 | L2 512 KB 0x703fe07a 0 1 1 1 0x1ff 0xf 0x2(64 bytes) 51 | 52 | -------------------------------------------------------------------------------- /firmware/vc4_include/exception.h: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | VideoCore4 exceptions. 17 | 18 | This file in the public release documents all exception names: 19 | brcm_usrlib\dag\vmcsx\vcfw\rtos\none\rtos_none.c 20 | 21 | =============================================================================*/ 22 | 23 | #pragma once 24 | 25 | #define VC4_EXC_ZERO 0 26 | #define VC4_EXC_MISALIGNED 1 27 | #define VC4_EXC_DIVIDE_BY_ZERO 2 28 | #define VC4_EXC_UNDEF 3 29 | #define VC4_EXC_FORBIDDEN 4 30 | #define VC4_EXC_ILLEGAL_MEM 5 31 | #define VC4_EXC_BUS_ERROR 6 32 | #define VC4_EXC_FPE 7 33 | #define VC4_EXC_ISP 8 34 | #define VC4_EXC_DUMMY 9 35 | #define VC4_EXC_ICACHE 10 36 | #define VC4_EXC_VEC_CORE 11 37 | #define VC4_EXC_L2_ALIAS 12 38 | #define VC4_EXC_BKPT 13 39 | 40 | #define VC4_EXC_NAMES \ 41 | "Zero", \ 42 | "Misaligned", \ 43 | "Division by zero", \ 44 | "Undefined instruction", \ 45 | "Forbidden instruction", \ 46 | "Illegal memory", \ 47 | "Bus error", \ 48 | "Floating point exception", \ 49 | "ISP", \ 50 | "Dummy", \ 51 | "ICache", \ 52 | "Vector core exception", \ 53 | "Bad L2 alias", \ 54 | "Breakpoint" 55 | -------------------------------------------------------------------------------- /common/BCM2708Gpio.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void BCM2708Gpio::setFunction(uint8_t pin_num, BCM2708PinmuxSetting function) { 4 | volatile uint32_t* fsel = reinterpret_cast(&GP_FSEL0); 5 | uint8_t regnum = pin_num / 10; 6 | 7 | uint8_t pin_shift = (pin_num % 10) * 3; 8 | 9 | fsel[regnum] = (fsel[regnum] & ~(0x7 << pin_shift)) | (function << pin_shift); 10 | } 11 | 12 | void BCM2708Gpio::getAllFunctions(BCM2708PinmuxSetting *functions) { 13 | volatile uint32_t* fsel = reinterpret_cast(&GP_FSEL0); 14 | for (int bank=0; bank<7; bank++) { 15 | int pins_in_bank = (bank == 6) ? 4 : 10; 16 | for (int pin=0; pin < pins_in_bank; pin++) { 17 | functions[(bank * 10) + pin] = static_cast((fsel[bank] >> (pin * 3)) & 0x7); 18 | } 19 | } 20 | } 21 | 22 | void BCM2708Gpio::clearPin(uint8_t pin_num) { 23 | volatile uint32_t *clear = reinterpret_cast(&GP_CLR0); 24 | uint8_t regnum = pin_num / 32; 25 | uint8_t pin_shift = pin_num % 32; 26 | 27 | clear[regnum] = 1 << pin_shift; 28 | } 29 | 30 | void BCM2708Gpio::setPin(uint8_t pin_num) { 31 | volatile uint32_t *clear = reinterpret_cast(&GP_SET0); 32 | uint8_t regnum = pin_num / 32; 33 | uint8_t pin_shift = pin_num % 32; 34 | 35 | clear[regnum] = 1 << pin_shift; 36 | } 37 | 38 | bool BCM2708Gpio::getPin(uint8_t pin_num) { 39 | const volatile uint32_t *level = reinterpret_cast(&GP_LEV0); 40 | uint8_t regnum = pin_num / 32; 41 | uint8_t pin_shift = pin_num % 32; 42 | 43 | return level[regnum] & (1 << pin_shift); 44 | } 45 | 46 | uint32_t BCM2708Gpio::getBank(uint8_t bank) { 47 | const volatile uint32_t *level = reinterpret_cast(&GP_LEV0); 48 | return level[bank]; 49 | } 50 | 51 | BCM2708Gpio gGPIO {}; 52 | -------------------------------------------------------------------------------- /firmware/aux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "uart.h" 5 | #include "pll_read.h" 6 | #include "aux.h" 7 | 8 | #define AUXXENG *((volatile uint32_t*)(0x7E215004)) 9 | #define AUX_MU_IO_REG *((volatile uint32_t*)(0x7E215040)) 10 | #define AUX_MU_IIR_REG *((volatile uint32_t*)(0x7E215044)) 11 | #define AUX_MU_IER_REG *((volatile uint32_t*)(0x7E215048)) 12 | #define AUX_MU_LCR_REG *((volatile uint32_t*)(0x7E21504c)) 13 | #define AUX_MU_MCR_REG *((volatile uint32_t*)(0x7E215050)) 14 | #define AUX_MU_LSR_REG *((volatile uint32_t*)(0x7E215054)) 15 | #define AUX_MU_CNTL_REG *((volatile uint32_t*)(0x7E215060)) 16 | #define AUX_MU_BAUD *((volatile uint32_t*)(0x7E215068)) 17 | 18 | struct uart_device aux_uart = { &AUX_MU_IO_REG, &AUX_MU_LSR_REG }; 19 | FILE *aux_fd = 0; 20 | 21 | static void uart_putchar(struct uart_device *uart, char c) { 22 | if (c == '\n') uart_putchar(uart, '\r'); 23 | while ((*(uart->lsr_reg) & 0x20) == 0); 24 | *(uart->data_reg) = c; 25 | } 26 | 27 | void aux_flush() { 28 | while ((AUX_MU_LSR_REG & 0x40) == 0); 29 | } 30 | 31 | static int uart_write(struct uart_device *uart, const char *str, int length) { 32 | for (int i=0; i AIUI, the country code leads to "disablement" of (5GHz) WiFi channels that are restricted/illegal in the country specified (and may be other WiFi channel associated things too) as required by certification (of the WiFi module?) for use in the associated country. Totally separate from keyboard layout etc. 3 | 4 | https://www.raspberrypi.org/forums/viewtopic.php?f=98&t=292691 5 | > BCM43438 on Zero/3A/3B 6 | > BCM43455 on 3A+/3B+/4B/CM4 7 | > BCM43456 on 400 8 | > CM4 is BCM43455. 9 | > CM4 is CYW43455 10 | 11 | 12 | https://www.raspberrypi.org/forums/viewtopic.php?p=1586034#p1586034 13 | https://www.raspberrypi.org/forums/viewtopic.php?p=1586431#p1586431 14 | > You need to patch the WiFi firmware to enable monitor mode. 15 | > https://github.com/seemoo-lab/nexmon 16 | 17 | https://www.raspberrypi.org/forums/viewtopic.php?p=1547885#p1547885 18 | > https://sandilands.info/sgordon/capturing-wifi-in-monitor-mode-with-iw 19 | 20 | https://www.raspberrypi.org/forums/viewtopic.php?p=1806938#p1806938 21 | > Re: CYW43455 (3B+, 4B, CM4) WiFi feedback thread 22 | > The clm_blob file defines the channels that are available in each region, the rules associated with them, and how much power should be used for each one. It should be independent of firmware version, but you are advised to use the latest clm_blob. 23 | 24 | https://github.com/seemoo-lab/nexmon 25 | 2021-10-06 00:09:37 < muaddib[m]> Regardless I think the offensive security forums would be better suited for that as the creators of nexmon also contribute to Kali. 26 | https://www.bastibl.net/gnuradio-on-android/ 27 | https://static1.squarespace.com/static/543ae9afe4b0c3b808d72acd/t/55df1835e4b02d66e574c07a/1440684085213/3-rondeau_tom-android_intro-2015-08-27.pdf 28 | https://arxiv.org/pdf/1601.07077.pdf 29 | https://store.nethunter.com/en/packages/de.tu_darmstadt.seemoo.nexmon/ 30 | -------------------------------------------------------------------------------- /firmware/traps.S: -------------------------------------------------------------------------------- 1 | .macro SaveRegsLower 2 | stm lr, (--sp) 3 | stm r0-r5, (--sp) 4 | .endm 5 | 6 | .macro SaveRegsUpper 7 | stm r6-r15, (--sp) 8 | stm r16-r23, (--sp) 9 | .endm 10 | 11 | .macro SaveRegsAll 12 | SaveRegsLower 13 | SaveRegsUpper 14 | .endm 15 | 16 | .macro ExceptionHandler label, exception_number 17 | .global fleh_\label 18 | fleh_\label: 19 | SaveRegsLower 20 | mov r1, \exception_number 21 | b irq_fatal 22 | .endm 23 | 24 | .text 25 | irq_fatal: 26 | SaveRegsUpper 27 | mov r0, sp 28 | b sleh_fatal 29 | 30 | ExceptionHandler zero, #0 31 | ExceptionHandler misaligned, #1 32 | ExceptionHandler dividebyzero, #2 33 | ExceptionHandler undefinedinstruction, #3 34 | ExceptionHandler forbiddeninstruction, #4 35 | ExceptionHandler illegalmemory, #5 36 | ExceptionHandler buserror, #6 37 | ExceptionHandler floatingpoint, #7 38 | ExceptionHandler isp, #8 39 | ExceptionHandler dummy, #9 40 | ExceptionHandler icache, #10 41 | ExceptionHandler veccore, #11 42 | ExceptionHandler badl2alias, #12 43 | ExceptionHandler breakpoint, #13 44 | ExceptionHandler unknown, #14 45 | 46 | .global fleh_irq 47 | fleh_irq: 48 | SaveRegsAll 49 | mov r0, sp 50 | mov r1, r29 51 | di 52 | bl sleh_irq 53 | return_from_exception: 54 | ldm r16-r23, (sp++) 55 | ldm r6-r15, (sp++) 56 | ldm r0-r5, (sp++) 57 | ld lr, (sp++) 58 | rti 59 | 60 | .global dump_all_state 61 | dump_all_state: 62 | mov r1, 0xdeadbeef 63 | st r1, (--sp) 64 | mov r1, sr 65 | st r1, (--sp) 66 | stm lr, (--sp) 67 | stm r0-r5, (--sp) 68 | stm r6-r15, (--sp) 69 | stm r16-r23, (--sp) 70 | mov r1, r0 71 | mov r0, sp 72 | bl r1 73 | ldm r16-r23, (sp++) 74 | ldm r6-r15, (sp++) 75 | ldm r0-r5, (sp++) 76 | ld lr, (sp++) 77 | ld r0, (sp++) 78 | ld r0, (sp++) 79 | rts 80 | 81 | .global test_rti 82 | test_rti: 83 | st r0, (--sp) 84 | st r1, (--sp) 85 | rti 86 | 87 | .global swi1_test 88 | swi1_test: 89 | bl dump_all_state 90 | rti 91 | -------------------------------------------------------------------------------- /docs/vpu.txt: -------------------------------------------------------------------------------- 1 | MMIO writes appear to be async, the dummy irq can fire due to a bad write (power domain disabled target), but the pc will have advanced beyond the point of failure 2 | 3 | H(row,col) refers to 16 cells, spanning col to col+15 4 | 5 | rX = ((x&0x3f) << 6) | (y & 0x3f) 6 | H(row,col)+rX refers to 16 cells, starting at row+x col+y 7 | 8 | row/col must be immediates 9 | 10 | when doing byte-wise access, H(row,col), the col must be 16 aligned (0/16/32/48) 11 | when doing halfword access, HX(row,col), the col must be 32 aligned (0/32) 12 | when doing word access, HY(row,col), the col must be 0 13 | when in column mode (V, VX, VY), the same rules apply, but to the row# instead 14 | when using H_(row,col)+rX, you can break those rules 15 | 16 | 0,0 to 7,63 are initialized to 0 by the boot rom setting up the L2 cache 17 | it was doing a `v32mov H32(0++,0), 0 REP8`, then storing that 512 byte chunk to the L2 18 | 19 | vector contents survive a watchdog reset 20 | vector contents corrupted when RUN is held low 21 | 22 | v16add Vd,Va,Vb 23 | take 2 vectors of 16 ints, sign-extend asif they where 16bit?, add, save to Vd 24 | 25 | 26 | # mov with 32bit immediate 27 | 00 e8 78 56 34 12 mov r0,0x12345678 28 | 01 e8 78 56 34 12 mov r1,0x12345678 29 | 10 e8 78 56 34 12 mov r16,0x12345678 30 | 14 e8 78 56 34 12 mov r20,0x12345678 31 | 32 | # vector load 33 | 16 f8 38 c0 80 03 80 f8 04 00 v32ld HY(0++,0),(r1+=r2) REP64 34 | 10 f8 38 c0 80 03 80 f8 04 00 v32ld HY(0++,0),(r1+=r2) 35 | 10 f8 38 c0 80 03 c0 fb 04 00 v32ld HY(0++,0),(r1) 36 | 10 f0 38 c0 80 03 v32ld HY(0,0),(r0) 37 | 10 f0 38 c0 81 03 v32ld HY(0,0),(r1) 38 | 10 f0 38 c0 8f 03 v32ld HY(0,0),(r15) 39 | 10 f0 38 20 8f 03 v32ld H(0,16),(r15) 40 | 10 f0 38 a0 8f 03 v32ld HX(0,32),(r15) 41 | 0e f8 38 00 80 03 80 f8 04 00 v16ld H(0++,0),(r1+=r2) REP64 42 | 0e f8 38 80 80 03 80 f8 04 00 v16ld HX(0++,0),(r1+=r2) REP64 43 | 0e f8 38 c0 80 03 80 f8 04 00 v16ld HY(0++,0),(r1+=r2) REP64 44 | -------------------------------------------------------------------------------- /common/cxx_runtime.cc: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (C) 2016-2017 Authors of rpi-open-firmware 3 | All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | FILE DESCRIPTION 16 | Crappy C++ runtime. 17 | 18 | =============================================================================*/ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | extern uintptr_t* __init_array_start; 26 | extern uintptr_t* __init_array_end; 27 | 28 | #ifdef __arm__ 29 | // TODO, use split sections to just not include them at link time 30 | void* operator new[] (size_t sz) { 31 | return malloc(sz); 32 | } 33 | 34 | void* operator new (size_t sz) { 35 | return malloc(sz); 36 | } 37 | 38 | void operator delete (void* ptr) { 39 | free(ptr); 40 | } 41 | 42 | void operator delete[] (void* ptr) { 43 | free(ptr); 44 | } 45 | #endif 46 | 47 | extern "C" void __cxa_pure_virtual() { 48 | panic("__cxa_pure_virtual!"); 49 | } 50 | 51 | void __cxx_init() { 52 | unsigned ctor_count = (unsigned)(&__init_array_end - &__init_array_start); 53 | void (*static_ctor)(); 54 | 55 | //printf("__cxx_init: calling %d static constructors (0x%p - 0x%p) ...\n", ctor_count, &__init_array_start, &__init_array_end); 56 | 57 | for (unsigned i = 0; i < ctor_count; i++) { 58 | uintptr_t* ptr = (((uintptr_t*)&__init_array_start) + i); 59 | //printf("ctor#%d is %lx\n", i, *ptr); 60 | static_ctor = reinterpret_cast(*ptr); 61 | static_ctor(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /docs/arm-mmu.txt: -------------------------------------------------------------------------------- 1 | arm32 level1 page table 2 | 16kb long 3 | 32bit slots 4 | 4096 slots total 5 | each slot addresses a 1mb chunk of virtual space 6 | 7 | level2 page table 8 | 1kb long 9 | 32bit slots 10 | 256 slots total 11 | each slot addresses a 4kb chunk of virt space 12 | typically 4 level2's in a 4k page 13 | 14 | i probably want TTBR0 15 | use TTBCR to make entire space obey TTBR0 16 | TTBCR.N=0 means TTBR0 controls all 17 | i want TRE=0, no remapping types 18 | 19 | normal ram should be TEX=001, C=1, B=1, S=1 20 | AP? domain? nG? S? 21 | XN, execute never 22 | PXN, priv execute never 23 | NS, says to use the secure or nonsecure mappings 24 | 25 | 26 | 27 | short descriptor format 28 | TTBCR bits 2:0, the size of the memory split 29 | TTBR0 index comes from addr bits 31:(14-N) 30 | 31 | size fixed bits variable bits TTBR0-level1 size slots 32 | 0 31:14 13:0 16kb 4096 33 | 1 31:13 12:0 8kb 2048 34 | 2 31:12 11:0 4kb 1024 35 | 3 31:11 10:0 2kb 512 36 | 4 31:10 9:0 1kb 256 37 | 5 31:9 8:0 512b 128 38 | 6 31:8 7:0 256b 64 39 | 7 31:7 6:0 128b 32 40 | 41 | https://developer.arm.com/documentation/ddi0333/h/memory-management-unit/mmu-descriptors/first-level-descriptor-address 42 | https://documentation-service.arm.com/static/5e8e358afd977155116a8bb5?token= 43 | 44 | bits (32-N):20 of the virt addr, act as an index into TTBR0 45 | bits 31:20 of the virt addr act as ain index into TTBR1 46 | a mux then decides which to actually use, based on N and the split 47 | TTBR1 must always point to a 16kb table that is 16kb aligned, but the lower split is shadowed by TTBR0 and can be treated as free ram 48 | 49 | 2021-03-18 16:44:03 < Bitweasil> clever, if you were wondering, the Rpi2 does support the long descriptor/LPAE table types. 50 | 2021-03-18 16:44:50 < clever> Bitweasil: ah, nice 51 | 52 | -------------------------------------------------------------------------------- /firmware/trap.s: -------------------------------------------------------------------------------- 1 | .macro SaveRegsLower 2 | stm lr, (--sp) 3 | stm r0-r5, (--sp) 4 | .endm 5 | 6 | .macro SaveRegsUpper 7 | stm r6-r15, (--sp) 8 | stm r16-r23, (--sp) 9 | .endm 10 | 11 | .macro SaveRegsAll 12 | SaveRegsLower 13 | SaveRegsUpper 14 | .endm 15 | 16 | .macro ExceptionHandler label, exception_number 17 | .global fleh_\label 18 | fleh_\label: 19 | SaveRegsLower 20 | mov r1, \exception_number 21 | b irq_fatal 22 | .endm 23 | 24 | .text 25 | irq_fatal: 26 | SaveRegsUpper 27 | mov r0, sp 28 | b sleh_fatal 29 | 30 | ExceptionHandler zero, #0 31 | ExceptionHandler misaligned, #1 32 | ExceptionHandler dividebyzero, #2 33 | ExceptionHandler undefinedinstruction, #3 34 | ExceptionHandler forbiddeninstruction, #4 35 | ExceptionHandler illegalmemory, #5 36 | ExceptionHandler buserror, #6 37 | ExceptionHandler floatingpoint, #7 38 | ExceptionHandler isp, #8 39 | ExceptionHandler dummy, #9 40 | ExceptionHandler icache, #10 41 | ExceptionHandler veccore, #11 42 | ExceptionHandler badl2alias, #12 43 | ExceptionHandler breakpoint, #13 44 | ExceptionHandler unknown, #14 45 | 46 | .global fleh_irq 47 | fleh_irq: 48 | SaveRegsAll 49 | mov r0, sp 50 | mov r1, r29 51 | di 52 | bl sleh_irq 53 | return_from_exception: 54 | ldm r16-r23, (sp++) 55 | ldm r6-r15, (sp++) 56 | ldm r0-r5, (sp++) 57 | ld lr, (sp++) 58 | rti 59 | 60 | .global dump_all_state 61 | dump_all_state: 62 | mov r1, 0xdeadbeef 63 | st r1, (--sp) 64 | mov r1, sr 65 | st r1, (--sp) 66 | stm lr, (--sp) 67 | stm r0-r5, (--sp) 68 | stm r6-r15, (--sp) 69 | stm r16-r23, (--sp) 70 | mov r1, r0 71 | mov r0, sp 72 | bl r1 73 | ldm r16-r23, (sp++) 74 | ldm r6-r15, (sp++) 75 | ldm r0-r5, (sp++) 76 | ld lr, (sp++) 77 | ld r0, (sp++) 78 | ld r0, (sp++) 79 | rts 80 | 81 | .global test_rti 82 | test_rti: 83 | st r0, (--sp) 84 | st r1, (--sp) 85 | rti 86 | 87 | .global swi1_test 88 | swi1_test: 89 | bl dump_all_state 90 | rti 91 | 92 | -------------------------------------------------------------------------------- /common/pl011.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "hardware.h" 4 | #include "pll_read.h" 5 | 6 | #define UART_IBRD *((volatile uint32_t*)(0x7e201024)) 7 | #define UART_FBRD *((volatile uint32_t*)(0x7e201028)) 8 | #define UART_LCRH *((volatile uint32_t*)(0x7e20102c)) 9 | #define UART_CR *((volatile uint32_t*)(0x7e201030)) 10 | #define UART_ICR *((volatile uint32_t*)(0x7e201044)) 11 | 12 | static char buffer[512]; 13 | 14 | static void pl011_flush(); 15 | static int uart_write(void *uart, const char *str, int length); 16 | 17 | #ifdef BAREMETAL 18 | //FILE *funopen(void *cookie, int (*read)(void*, char *, int), int (*write)(void*, const char*, int), int, int); 19 | 20 | void pl011_putchar(unsigned char c) { 21 | if (c == '\n') pl011_putchar('\r'); 22 | while(UART_MSR & 0x20); 23 | UART_RBRTHRDLL = c; 24 | } 25 | 26 | void pl011_uart_init(uint32_t baud) { 27 | pl011_flush(); 28 | UART_CR = 0; 29 | 30 | if (CM_UARTDIV == 0) { 31 | // CM_UARTDIV can range from 0 to 1023 with a fractional resolution of 1/4096th 32 | // on the rpi1-3, this sets the freq to 19.2 / (0x6666 / 0x1000) == ~3mhz 33 | // TODO, have a better default for other models? 34 | CM_UARTDIV = CM_PASSWORD | 0x3900; 35 | CM_UARTCTL = CM_PASSWORD | CM_SRC_OSC | CM_UARTCTL_FRAC_SET | CM_UARTCTL_ENAB_SET; 36 | } 37 | uint32_t uart_freq = get_uart_base_freq(); 38 | uint32_t divisor = (uart_freq << 6) / baud / 16; 39 | 40 | UART_ICR = 0x7ff; // clear all interrupt flags 41 | UART_LCRH = 0x70; // fifo enable, 8bit mode 42 | 43 | // 0-65525 range, with 1/64th resolution 44 | UART_IBRD = (divisor >> 6) & 0xffff; 45 | UART_FBRD = divisor & 0x3f; 46 | UART_CR = 0x301; 47 | 48 | stdout = funopen(0, 0, uart_write, 0, 0); 49 | setvbuf(stdout, buffer, _IOLBF, 512); 50 | //printf("baud set to %ld with a divisor of %ld\n", (uart_freq << 6) / divisor / 16, divisor); 51 | } 52 | 53 | static int uart_write(void *uart, const char *str, int length) { 54 | for (int i=0; i EventM Name DialogReply 18 | } 19 | 20 | renderMainMenu :: MainMenuState -> AppState -> [ Widget Name ] 21 | renderMainMenu MainMenuState{psMenuState} _ = [ root ] 22 | where 23 | root = vBox [ menu ] 24 | menu = B.borderWithLabel (str "Menu") $ padLeftRight 1 $ L.renderList renderRow True psMenuState 25 | renderRow :: Bool -> MenuChoices -> Widget Name 26 | renderRow _ ShowAltModes = str "1: show gpio alt modes" 27 | renderRow _ PlayWithDither = str "2: play with hvs dither config" 28 | 29 | handleEvents :: MainMenuState -> AppState -> BrickEvent Name CustomEvent -> EventM Name DialogReply 30 | handleEvents mms@MainMenuState{psMenuState,psCallback} as@AppState{asMmioWindow,asReplyChan} event = do 31 | let 32 | openThing :: EventM Name DialogReply 33 | openThing = do 34 | case L.listSelectedElement psMenuState of 35 | Just (_index, item) -> case item of 36 | ShowAltModes -> do 37 | spawnAltModeViewer asMmioWindow asReplyChan (pure $ mkMainMenu mms) 38 | PlayWithDither -> do 39 | spawnPlayWithDither asMmioWindow asReplyChan (pure $ DialogReplyContinue $ mkMainMenu mms) 40 | case event of 41 | VtyEvent (V.EvKey (V.KChar 'q') []) -> do 42 | psCallback as 43 | VtyEvent (V.EvKey V.KEnter []) -> do 44 | openThing 45 | VtyEvent evt -> do 46 | newlist <- L.handleListEventVi L.handleListEvent evt psMenuState 47 | pure $ DialogReplyContinue $ mkMainMenu mms { psMenuState = newlist } 48 | 49 | mkMainMenu :: MainMenuState -> Dialog 50 | mkMainMenu s = Dialog { dRender = renderMainMenu s, dHandleEvent = handleEvents s } 51 | -------------------------------------------------------------------------------- /docs/pixelvalve.md: -------------------------------------------------------------------------------- 1 | register | offset 2 | --- | --- 3 | C | 0x0 4 | VC | 0x4 5 | `VSYNCD_EVEN` | 0x8 6 | HORZA | 0xc 7 | HORZB | 0x10 8 | VERTA | 0x14 9 | VERTB | 0x18 10 | `VERTA_EVEN` | 0x1c 11 | `VERTB_EVEN` | 0x20 12 | `INTEN` | 0x24 13 | `INTSTAT` | 0x28 14 | `STAT` | 0x2c 15 | `DSI_HACT_ACT` | 0x30 16 | 17 | ## PV C register 18 | bits | usage 19 | -----|----- 20 | 0 | enable 21 | 1 | fifo clear 22 | 2:3 | clock select, 0=dsi, 1=dpi/smi/hdmi, 2=vec 23 | 4:5 | pixel rep 24 | 12 | wait hstart 25 | 13 | trigger underflow 26 | 14 | clear at start 27 | 15:20| fifo full level bits 0:5 28 | 21:23| format 29 | 24 | unknown 30 | 25:26| fifo full level bits 6:7 (VC6 only) 31 | 32 | ## PV VC register 33 | bits | usage 34 | ---|--- 35 | 0 | video enable 36 | 1 | continous 37 | 2 | command 38 | 3 | dsi 39 | 4 | interlace 40 | 5 | odd first 41 | 6 | odd delay 42 | 43 | ## PV HORZA 44 | bits | usage 45 | ---|--- 46 | 0:15 | hsync 47 | 16:31 | h backporch 48 | 49 | ## PV HORZB 50 | bits | usage 51 | ---|--- 52 | 0:15 | hactive 53 | 16:31 | h frontporch 54 | 55 | ## PV VERTA 56 | bits | usage 57 | ---|--- 58 | 0:15 | vsync 59 | 16:31 | v backporch 60 | 61 | ## PV VERTB 62 | bits | usage 63 | ---|--- 64 | 0:15 | vactive 65 | 16:31 | v frontporch 66 | 67 | ## PV INTEN 68 | interrupt enable 69 | bits | usage 70 | ---|--- 71 | 0 | hsync start 72 | 1 | h backporch start 73 | 2 | hactive start 74 | 3 | h frontporch start 75 | 4 | vsync start 76 | 5 | v backporch start 77 | 6 | vactive start 78 | 7 | v frontporch start 79 | 8 | v frontporch end 80 | 9 | video idle 81 | ## PV INTSTAT 82 | interrupt status, same bits as INTEN 83 | 84 | # overview 85 | 86 | each scanline has HFP clocks worth of front porch, HSYNC clocks worth of hsync, HBP worth of back porch, and then HACTIVE clocks worth of pixel data 87 | 88 | on VC6, some PV's operate in DDR mode, and generate 2 pixels per clock, so all horizoncal timings need to be halved when put into the registers 89 | 90 | one field has VFP scanlines of frontporch, VSYNC scanlines of sync, VBP scanlines of backporch, and then VACTIVE scanlines of actual image data 91 | 92 | when interlacing is on, it will alternate between the normal VERTA/VERTB and `VERTA_EVEN`/`VERTB_EVEN` 93 | -------------------------------------------------------------------------------- /docs/jtag-raw.txt: -------------------------------------------------------------------------------- 1 | arm11 specs: 2 | 3 | IR is 5 bits wide 4 | IR=0 maps DR to EXTEST? to allow writing the scan chain selected by Scan_N 5 | IR=2 maps DR to Scan_N/SCREG 6 | IR=4 executes Restart? which lets the arm core execute normally, once back in Run-Test/Idle 7 | IR=8 executes Halt? forcing the arm core into a debug state 8 | IR=12 maps DR INTEST? to allow reading the scan chain selected by Scan_N 9 | IR=29 maps DR directly to ITR, skipping the Scan_N=4+EXTEST combo 10 | IR=30 maps DR to the IDcode register, 32 bits wide, capture-dr loads idcode into shiftreg, shift-dr exports it to the debugger 11 | IR=31 maps DR to bypass instruction, 1 bit wide 12 | 13 | 14 | IDcode on bcm2835's arm1176 core is 0x07b7617F 15 | 16 | DR registers: 17 | Scan_N is 5 bits wide 18 | 19 | use IR to map DR to Scan_N/INTEST/EXTEST 20 | 21 | INTEST is used to read a given scan-chain, and trigger any clear-upon-read actions 22 | EXTEST is used to write a given scan-chain, but also allows reading the previous value during the shifting, does not trigger clear-upon-read actions 23 | 24 | Scan_N=0 debug ID register DIDR, 8+32==40 bits long 25 | allows access of CP14 debug register 0, upper 8 bits hard-wired to 0x41(A) 26 | Scan_N=1 debug status and control register DSCR, 32 bits long 27 | allows access of CP14 debug register 1 28 | Scan_N=4 instruction transfer register ITR 1+32 == 33 bits long 29 | the processor must be in debug state 30 | DSCR[13] must be set 31 | Scan_N must be 4 or 5 32 | opcode in ITR is only executed while in Run-Test/Idle 33 | DSCR[6] must be clear 34 | bit 33 indicates if the loaded opcode has executed 35 | Scan_N=5 access to the DTR register and 2 status bits, 1+1+32 == 34 bits long 36 | writes will return nDTRempty++InstCompl++wDTR and set nRetry++Ready+rDTR 37 | reads return wDTRfull++InstCompl++wDTR 38 | Scan_N=6 embedded trace macrocell, 1+7+32 == 40 bits 39 | Scan_N=7 debug, 7+32+1 == 40 bits 40 | direct access to several debug related registers: VCR, PC, BRP, WRP 41 | 7bit addr, 32bit data, 1bit ReqCompl/ready/nRW 42 | 43 | 44 | COMMAND_HANDLER(arm11_handle_vcr) 45 | the openocd "vcr" command can be used to set the "vector catch register" on an arm1176 46 | that will cause a debug halt if certain exception vectors are taken 47 | 48 | -------------------------------------------------------------------------------- /firmware/utils4.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "pll_read.h" 5 | #include "utils.hh" 6 | 7 | // at a vpu freq of 500mhz 8 | // repeating a 16x mult 64 * 128 times took 17uS 9 | // 64 * 64 times took 9uS 10 | // 64 * 256 times took 33uS 11 | // 64 * 1024 times took 131uS 12 | // ~0.1279296875 uS to do a single `vmull.ss HX(0++,0), HX(0++,0), 2 REP64 ; addcmpbne %5, -1, 0, loop` 13 | // which comes to about 64 clock cycles 14 | void test_matrix_speed() { 15 | uint16_t a[1024]; 16 | for (int i=0; i<1024; i++) a[i] = i; 17 | 18 | uint32_t start, stop, count = 2048; 19 | #if 1 20 | __asm__ volatile ( 21 | // load 1024 int16's into 0,0 to 65,15 22 | "v16ld HX(0++,0), (%2+=%3) REP64\n" 23 | // load start time 24 | "ld %0, (%4)\n" 25 | "loop:" 26 | // multiply all 1024 by 2 27 | "vmull.ss HX(0++,0), HX(0++,0), 2 REP64\n" 28 | // repeat count times 29 | "addcmpbne %5, -1, 0, loop\n" 30 | // save stop time 31 | "ld %2, (%4)\n" 32 | : "=&r"(start), "=r"(stop) 33 | : "r"(a), "r"(2*16), "r"(&ST_CLO), "r"(count) 34 | : "memory"); 35 | #endif 36 | printf("16 * 64 * %ld mult + %ld addcmpbne took time delta %lu uS\n", count, count, stop - start); 37 | uint32_t vpu_freq = get_vpu_per_freq(); 38 | printf("vpu freq is %lu\n", vpu_freq); 39 | // > ((64 * 1024) / 500000015) * 1000 * 1000 40 | // 131.07199606784013 41 | // > ((64 * 2048) / 500000015) * 1000 * 1000 42 | // 262.14399213568026 43 | // 64 * count / vpu_freq == total time spent in loop 44 | } 45 | 46 | void test_matrix_big_mult() { 47 | uint16_t a[1024]; 48 | for (int i=0; i<1024; i++) a[i] = i; 49 | 50 | #if 1 51 | __asm__ volatile ( 52 | // load 1024 int16's into 0,0 to 65,15 53 | "v16ld HX(0++,0), (%0+=%1) REP64\n" 54 | // multiply all 1024 by 2 55 | "vmull.ss HX(0++,0), HX(0++,0), 2 REP64\n" 56 | // save all 1024 back to ram 57 | "v16st HX(0++,0), (%0+=%1) REP64" 58 | : 59 | : "r"(a), "r"(2*16) 60 | : "memory"); 61 | #endif 62 | for (int i=0; i<64; i++) { 63 | for (int j=0; j<16; j++) { 64 | int index = (i*16) + j; 65 | printf("%5d*2==%5u", index, a[index]); 66 | } 67 | printf("\n"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /arm64/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define UART_DR 0x3f201000 6 | #define UART_FR 0x3f201018 7 | 8 | #define REG32(x) ( (volatile uint32_t*)(x) ) 9 | 10 | #define logf(fmt, ...) { print_timestamp(); printf("[BRINGUP:%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); } 11 | 12 | int boot_count = 0; 13 | 14 | void drop_privs(uint64_t link, uint64_t spsr, uint64_t scr); 15 | void reentry(); 16 | 17 | void uart_putc(char c) { 18 | while (*REG32(UART_FR) & 0x20); 19 | 20 | *REG32(UART_DR) = c; 21 | } 22 | 23 | #define showreg(reg) { uint64_t t; __asm__ volatile ("mrs %0," #reg : "=r"(t)); printf(#reg ": 0x%016x\n", t); } 24 | 25 | void dump_things() { 26 | showreg(CurrentEL); 27 | showreg(S3_1_C15_C3_0); 28 | uint64_t currentel; 29 | __asm__ volatile ("mrs %0, CurrentEL" : "=r"(currentel)); 30 | switch (currentel) { 31 | case 0xc: 32 | logf("EL3 regs:\n"); 33 | showreg(RVBAR_EL3); 34 | showreg(VBAR_EL3); 35 | showreg(SCR_EL3); 36 | case 0x8: 37 | logf("EL2 regs:\n"); 38 | showreg(VBAR_EL2); 39 | showreg(SCR_EL2); 40 | case 0x4: 41 | logf("EL1 regs:\n"); 42 | showreg(RVBAR_EL1); 43 | showreg(SCR_EL1); 44 | } 45 | } 46 | 47 | #define SPSR_EL_M_EL2H 0x9 48 | 49 | void handle_exception200(uint64_t CurrentEL, uint64_t elr, uint64_t esr) { 50 | puts("exception handler 0x200"); 51 | printf("CurrentEL: %x\nELR: %x\nESR: %x\n", CurrentEL, elr, esr); 52 | showreg(FAR_EL3); 53 | showreg(SP_EL0); 54 | showreg(SP_EL1); 55 | showreg(SP_EL2); 56 | showreg(SPSR_EL3); 57 | uint64_t spsr; 58 | __asm__("mrs %0, SPSR_EL3": "=r"(spsr)); 59 | printf("M: 0x%x\nM[4]:%d\nIL:%d\n", spsr & 0xf, (spsr >> 4) & 1, (spsr >> 20) & 1); 60 | showreg(ESR_EL3); 61 | printf("EC: 0x%x\n", (esr >> 26) & 0x3f); 62 | } 63 | 64 | void main() { 65 | while(ARM_ID != ARM_IDVAL); 66 | puts("hello world"); 67 | uint8_t c = 'A'; 68 | asm volatile("msr DBGDTRTX_EL0, %0":: "r" (c)); 69 | logf("Started on ARM, continuing boot from here ...\n"); 70 | logf("boot_count: %d\n", boot_count++); 71 | dump_things(); 72 | puts("dropping privs"); 73 | // TODO: set the A/I/F bits to 1 74 | drop_privs(reentry, ((0b1111 << 6) | 9), 1<<10 | 0xf); 75 | } 76 | 77 | void el2_main() { 78 | logf("now in el2?\n"); 79 | dump_things(); 80 | } 81 | -------------------------------------------------------------------------------- /firmware/otp_asm.s: -------------------------------------------------------------------------------- 1 | # 1 "otp_asm.S" 2 | # 1 "" 3 | # 1 "" 4 | # 1 "otp_asm.S" 5 | 6 | 7 | A2W_BASE = 0x7e102000 8 | A2W_XOSC0 = 0x090 9 | 10 | OTP_BASE = 0x7e20f000 11 | OTP_CONFIG_REG = 0x04 12 | OTP_CTRL_LO_REG = 0x08 13 | OTP_CTRL_HI_REG = 0x0c 14 | OTP_STATUS_REG = 0x10 15 | OTP_DATA_REG = 0x18 16 | OTP_ADDR_REG = 0x1c 17 | 18 | 19 | 20 | 21 | OTP_READY_BIT = 0 22 | 23 | 24 | .text 25 | .global otp_read_internal 26 | otp_read_internal: 27 | stm r6-r7,lr,(--sp) 28 | 29 | mov r6, r0 30 | bl otp_open 31 | mov r0, r6 32 | bl otp_read_reg 33 | mov r7, r0 34 | bl otp_close 35 | mov r0, r7 36 | 37 | ldm r6-r7,pc,(sp++) 38 | 39 | otp_open: 40 | stm lr, (--sp) 41 | mov r2, 0x03 42 | mov r1, OTP_BASE 43 | mov r3, A2W_BASE + A2W_XOSC0 44 | st r2, (r1 + OTP_CONFIG_REG) 45 | 46 | mov r0, 2 47 | 1: 48 | ld r2, (r3) 49 | addcmpbge r0, -1, 0, 1b 50 | 51 | mov r2, 0 52 | st r2, (r1 + OTP_CTRL_HI_REG) 53 | st r2, (r1 + OTP_CTRL_LO_REG) 54 | 55 | mov r0, 2 56 | 1: 57 | ld r2, (r3) 58 | addcmpbge r0, -1, 0, 1b 59 | 60 | mov r2, 0x2 61 | st r2, (r1 + OTP_CONFIG_REG) 62 | ldm pc, (sp++) 63 | 64 | otp_read_reg: 65 | stm lr, (--sp) 66 | mov r1, OTP_BASE 67 | mov r3, A2W_BASE + A2W_XOSC0 68 | st r0, (r1 + OTP_ADDR_REG) 69 | 70 | mov r0, 2 71 | 1: 72 | ld r2, (r3) 73 | addcmpbge r0, -1, 0, 1b 74 | 75 | mov r2, 0 76 | ld r0, (r1 + OTP_ADDR_REG) 77 | st r2, (r1 + OTP_CTRL_HI_REG) 78 | st r2, (r1 + OTP_CTRL_LO_REG) 79 | 80 | mov r0, 2 81 | 1: 82 | ld r2, (r3) 83 | addcmpbge r0, -1, 0, 1b 84 | 85 | mov r2, 1 86 | ld r0, (r1 + OTP_CTRL_LO_REG) 87 | st r2, (r1 + OTP_CTRL_LO_REG) 88 | ld r0, (r1 + OTP_CTRL_LO_REG) 89 | 1: 90 | mov r0, 2 91 | 2: 92 | ld r2, (r3) 93 | addcmpbge r0, -1, 0, 2b 94 | 95 | ld r0, (r1 + OTP_STATUS_REG) 96 | btest r0, OTP_READY_BIT 97 | beq 1b 98 | ld r0, (r1 + OTP_DATA_REG) 99 | ldm pc, (sp++) 100 | 101 | otp_close: 102 | stm lr, (--sp) 103 | mov r2, 0 104 | mov r1, OTP_BASE 105 | mov r3, A2W_BASE + A2W_XOSC0 106 | st r2, (r1 + OTP_CTRL_HI_REG) 107 | st r2, (r1 + OTP_CTRL_LO_REG) 108 | 109 | mov r0, 2 110 | 1: 111 | ld r2, (r3) 112 | addcmpbge r0, -1, 0, 1b 113 | 114 | mov r2, 0 115 | st r2, (r1 + OTP_CONFIG_REG) 116 | ldm pc, (sp++) 117 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/timer.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define ST_BASE 0x7e003000 3 | #define ST_CS HW_REGISTER_RW( 0x7e003000 ) 4 | #define ST_CS_MASK 0xffffffff 5 | #define ST_CS_WIDTH 32 6 | #define ST_CS_RESET 0000000000 7 | #if defined(__CC_ARM) 8 | #define ST_CLO vcos_getmicrosecs() 9 | #else 10 | #define ST_CLO HW_REGISTER_RO( 0x7e003004 ) 11 | #endif 12 | #define ST_CLO_MASK 0xffffffff 13 | #define ST_CLO_WIDTH 32 14 | #define ST_CHI HW_REGISTER_RO( 0x7e003008 ) 15 | #define ST_CHI_MASK 0xffffffff 16 | #define ST_CHI_WIDTH 32 17 | #define ST_C0 HW_REGISTER_RW( 0x7e00300c ) 18 | #define ST_C0_MASK 0xffffffff 19 | #define ST_C0_WIDTH 32 20 | #define ST_C0_RESET 0000000000 21 | #define ST_C1 HW_REGISTER_RW( 0x7e003010 ) 22 | #define ST_C1_MASK 0xffffffff 23 | #define ST_C1_WIDTH 32 24 | #define ST_C1_RESET 0000000000 25 | #define ST_C2 HW_REGISTER_RW( 0x7e003014 ) 26 | #define ST_C2_MASK 0xffffffff 27 | #define ST_C2_WIDTH 32 28 | #define ST_C2_RESET 0000000000 29 | #define ST_C3 HW_REGISTER_RW( 0x7e003018 ) 30 | #define ST_C3_MASK 0xffffffff 31 | #define ST_C3_WIDTH 32 32 | #define ST_C3_RESET 0000000000 33 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/cryptohw.h: -------------------------------------------------------------------------------- 1 | /*============================================================================= 2 | Copyright (c) 2007 Broadcom Europe Limited. All rights reserved. 3 | 4 | Project : BCM2707 5 | Module : CRYPTO wrapper hardware header 6 | File : $RCSfile: cryptohw.h,v $ 7 | Revision : $Revision: 1.2 $ 8 | 9 | FILE DESCRIPTION 10 | Definition of bits within CRYPTO hardware registers. 11 | =============================================================================*/ 12 | 13 | #ifndef CRYPTOHW_H 14 | #define CRYPTOHW_H 15 | 16 | #define CRYPTO_READFIELD(_w,_f) (((unsigned long)(_w) / _f) & (_f##_MASK)) 17 | 18 | enum 19 | { 20 | // BCM2707 has no crypto hardware but supports RNG interrupt 21 | // CRYPTO_ISR_RNG_INT = (1 << 2), 22 | CRYPTO_ISR_PKA_INT = (1 << 1), 23 | CRYPTO_ISR_SPU_INT = (1 << 0), 24 | 25 | // CRYPTO_IMR_RNG_INT_EN = (1 << 2), 26 | CRYPTO_IMR_PKA_INT_EN = (1 << 1), 27 | CRYPTO_IMR_SPU_INT_EN = (1 << 0), 28 | 29 | CRYPTO_CLK_CFG_PKA_CLK = (1 << 8), 30 | CRYPTO_CLK_CFG_PKA_CLK_MASK = 3, 31 | CRYPTO_CLK_CFG_PKA_CLK_FULL = 0, 32 | CRYPTO_CLK_CFG_PKA_CLK_HALF = 1, 33 | CRYPTO_CLK_CFG_PKA_CLK_THIRD = 2, 34 | CRYPTO_CLK_CFG_PKA_CLK_DISABLED = 3, 35 | 36 | CRYPTO_CLK_CFG_SPU_CLK = (1 << 4), 37 | CRYPTO_CLK_CFG_SPU_CLK_MASK = 3, 38 | CRYPTO_CLK_CFG_SPU_CLK_FULL = 0, 39 | CRYPTO_CLK_CFG_SPU_CLK_HALF = 1, 40 | CRYPTO_CLK_CFG_SPU_CLK_THIRD = 2, 41 | CRYPTO_CLK_CFG_SPU_CLK_DISABLED = 3, 42 | 43 | CRYPTO_CLK_CFG_OTP_CLKDIV = (1 << 0), 44 | CRYPTO_CLK_CFG_OTP_CLKDIV_MASK = 0xf, 45 | 46 | CRYPTO_CLK_CFG_OTP_CLKDIV_2 = 0x0, 47 | CRYPTO_CLK_CFG_OTP_CLKDIV_4 = 0x1, 48 | CRYPTO_CLK_CFG_OTP_CLKDIV_6 = 0x2, 49 | CRYPTO_CLK_CFG_OTP_CLKDIV_8 = 0x3, 50 | CRYPTO_CLK_CFG_OTP_CLKDIV_10 = 0x4, 51 | CRYPTO_CLK_CFG_OTP_CLKDIV_12 = 0x5, 52 | CRYPTO_CLK_CFG_OTP_CLKDIV_14 = 0x6, 53 | CRYPTO_CLK_CFG_OTP_CLKDIV_16 = 0x7, 54 | CRYPTO_CLK_CFG_OTP_CLKDIV_18 = 0x8, 55 | CRYPTO_CLK_CFG_OTP_CLKDIV_20 = 0x9, 56 | CRYPTO_CLK_CFG_OTP_CLKDIV_22 = 0xa, 57 | CRYPTO_CLK_CFG_OTP_CLKDIV_24 = 0xb, 58 | CRYPTO_CLK_CFG_OTP_CLKDIV_26 = 0xc, 59 | CRYPTO_CLK_CFG_OTP_CLKDIV_28 = 0xd, 60 | CRYPTO_CLK_CFG_OTP_CLKDIV_30 = 0xe, 61 | CRYPTO_CLK_CFG_OTP_CLKDIV_32 = 0xf, 62 | 63 | CRYPTO_SIMCTRL_DEBUG = (1 << 0), 64 | CRYPTO_SIMCTRL_SECURE = (1 << 1) 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/tectl.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define TE_BASE 0x7e20e000 3 | #define TE_APB_ID 0x00746563 4 | #define TE_0C HW_REGISTER_RW( 0x7e20e000 ) 5 | #define TE_0C_MASK 0xffffffff 6 | #define TE_0C_WIDTH 32 7 | #define TE_0VSWIDTH HW_REGISTER_RW( 0x7e20e004 ) 8 | #define TE_0VSWIDTH_MASK 0xffffffff 9 | #define TE_0VSWIDTH_WIDTH 32 10 | #define TE_0TIMER HW_REGISTER_RW( 0x7e20e008 ) 11 | #define TE_0TIMER_MASK 0xffffffff 12 | #define TE_0TIMER_WIDTH 32 13 | #define TE_1C HW_REGISTER_RW( 0x7e20e00c ) 14 | #define TE_1C_MASK 0xffffffff 15 | #define TE_1C_WIDTH 32 16 | #define TE_1VSWIDTH HW_REGISTER_RW( 0x7e20e010 ) 17 | #define TE_1VSWIDTH_MASK 0xffffffff 18 | #define TE_1VSWIDTH_WIDTH 32 19 | #define TE_1TIMER HW_REGISTER_RW( 0x7e20e014 ) 20 | #define TE_1TIMER_MASK 0xffffffff 21 | #define TE_1TIMER_WIDTH 32 22 | #define TE_2C HW_REGISTER_RW( 0x7e20e018 ) 23 | #define TE_2C_MASK 0xffffffff 24 | #define TE_2C_WIDTH 32 25 | #define TE_2VSWIDTH HW_REGISTER_RW( 0x7e20e01c ) 26 | #define TE_2VSWIDTH_MASK 0xffffffff 27 | #define TE_2VSWIDTH_WIDTH 32 28 | #define TE_2TIMER HW_REGISTER_RW( 0x7e20e020 ) 29 | #define TE_2TIMER_MASK 0xffffffff 30 | #define TE_2TIMER_WIDTH 32 31 | -------------------------------------------------------------------------------- /common/broadcom/bcm2708_chip/ccp2tx_a0.h: -------------------------------------------------------------------------------- 1 | // This file was generated by the create_regs script 2 | #define CCP2TX_BASE 0x7e001000 3 | #define CCP2TX_APB_ID 0x63637032 4 | #define CCP2TX_TC HW_REGISTER_RW( 0x7e001000 ) 5 | #define CCP2TX_TC_MASK 0xffffffff 6 | #define CCP2TX_TC_WIDTH 32 7 | #define CCP2TX_TS HW_REGISTER_RW( 0x7e001004 ) 8 | #define CCP2TX_TS_MASK 0xffffffff 9 | #define CCP2TX_TS_WIDTH 32 10 | #define CCP2TX_TPC HW_REGISTER_RW( 0x7e001008 ) 11 | #define CCP2TX_TPC_MASK 0xffffffff 12 | #define CCP2TX_TPC_WIDTH 32 13 | #define CCP2TX_TSC HW_REGISTER_RW( 0x7e00100c ) 14 | #define CCP2TX_TSC_MASK 0xffffffff 15 | #define CCP2TX_TSC_WIDTH 32 16 | #define CCP2TX_TIC HW_REGISTER_RW( 0x7e001010 ) 17 | #define CCP2TX_TIC_MASK 0xffffffff 18 | #define CCP2TX_TIC_WIDTH 32 19 | #define CCP2TX_TTC HW_REGISTER_RW( 0x7e001014 ) 20 | #define CCP2TX_TTC_MASK 0xffffffff 21 | #define CCP2TX_TTC_WIDTH 32 22 | #define CCP2TX_TBA HW_REGISTER_RW( 0x7e001018 ) 23 | #define CCP2TX_TBA_MASK 0xffffffff 24 | #define CCP2TX_TBA_WIDTH 32 25 | #define CCP2TX_TDL HW_REGISTER_RW( 0x7e00101c ) 26 | #define CCP2TX_TDL_MASK 0xffffffff 27 | #define CCP2TX_TDL_WIDTH 32 28 | #define CCP2TX_TD HW_REGISTER_RW( 0x7e001020 ) 29 | #define CCP2TX_TD_MASK 0xffffffff 30 | #define CCP2TX_TD_WIDTH 32 31 | -------------------------------------------------------------------------------- /firmware/pll_read.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "pll_read.h" 4 | 5 | uint32_t xtal_freq; 6 | 7 | uint32_t get_vpu_per_freq() { 8 | return clk_get_freq(&CM_VPUDIV, &CM_VPUCTL); 9 | } 10 | 11 | uint32_t get_uart_base_freq() { 12 | return clk_get_freq(&CM_UARTDIV, &CM_UARTCTL); 13 | } 14 | 15 | uint32_t compute_pll_freq(uint32_t ctrl, uint32_t frac) { 16 | uint32_t ndiv = A2W_PLLC_CTRL & A2W_PLLC_CTRL_NDIV_SET; 17 | uint32_t pdiv = (A2W_PLLC_CTRL & A2W_PLLC_CTRL_PDIV_SET) >> A2W_PLLC_CTRL_PDIV_LSB; 18 | uint64_t mult1 = (ndiv << 20) | frac; 19 | mult1 *= pdiv; 20 | // TODO, the optional /2 phase 21 | uint32_t freq = (xtal_freq * mult1) >> 20; 22 | return freq; 23 | } 24 | 25 | uint32_t plla() { 26 | return compute_pll_freq(A2W_PLLA_CTRL, A2W_PLLA_FRAC & A2W_PLLA_FRAC_MASK); 27 | } 28 | 29 | uint32_t pllb() { 30 | return compute_pll_freq(A2W_PLLB_CTRL, A2W_PLLB_FRAC & A2W_PLLB_FRAC_MASK); 31 | } 32 | 33 | uint32_t pllc() { 34 | //uint32_t ana1 = A2W_PLLC_ANA1; 35 | uint32_t ctrl = A2W_PLLC_CTRL; 36 | uint32_t frac = A2W_PLLC_FRAC & A2W_PLLC_FRAC_MASK; 37 | return compute_pll_freq(ctrl, frac); 38 | } 39 | 40 | uint32_t plld() { 41 | return compute_pll_freq(A2W_PLLD_CTRL, A2W_PLLD_FRAC & A2W_PLLD_FRAC_MASK); 42 | } 43 | 44 | uint32_t pllh() { 45 | return compute_pll_freq(A2W_PLLH_CTRL, A2W_PLLH_FRAC & A2W_PLLH_FRAC_MASK); 46 | } 47 | 48 | uint32_t pllc_core0() { 49 | uint32_t ctrl = A2W_PLLC_CORE0; 50 | uint32_t div = ctrl & A2W_PLLC_CORE0_DIV_SET; 51 | uint32_t pllc_freq = pllc(); 52 | return pllc_freq / div; 53 | } 54 | 55 | uint32_t clk_get_freq(volatile uint32_t *divreg, volatile uint32_t *ctlreg) { 56 | uint32_t div = *divreg; 57 | if (div == 0) return 0; 58 | uint64_t input_freq = clk_get_input_freq(ctlreg); 59 | return ((input_freq << 12) / div); 60 | } 61 | 62 | uint32_t clk_get_input_freq(volatile uint32_t *ctlreg) { 63 | uint32_t ctl = *ctlreg; 64 | switch (ctl & 0xf) { 65 | case 0: // GND clock source 66 | return 0; 67 | case 1: // crystal oscilator 68 | return xtal_freq; 69 | case 2: // test debug 0 70 | case 3: // test debug 1 71 | return 0; 72 | case 4: // plla 73 | return 0; 74 | case 5: // pllc_core0 75 | return pllc_core0(); 76 | case 6: // plld_per 77 | return 0; 78 | case 7: // pllh_aux 79 | return 0; 80 | case 8: // pllc_core1? 81 | return 0; 82 | case 9: // pllc_core2? 83 | return 0; 84 | default: 85 | return 0; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /dts/bcm2837-rpi-3-b.dts: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-2.0 2 | /dts-v1/; 3 | #include "bcm2837.dtsi" 4 | #include "bcm2836-rpi.dtsi" 5 | #include "bcm283x-rpi-smsc9514.dtsi" 6 | #include "bcm283x-rpi-usb-host.dtsi" 7 | #include "bcm283x-rpi-csi1-2lane.dtsi" 8 | 9 | / { 10 | compatible = "raspberrypi,3-model-b", "brcm,bcm2837"; 11 | model = "Raspberry Pi 3 Model B"; 12 | 13 | chosen { 14 | /* 8250 auxiliary UART instead of pl011 */ 15 | stdout-path = "serial1:115200n8"; 16 | }; 17 | 18 | memory { 19 | reg = <0 0x40000000>; 20 | }; 21 | 22 | leds { 23 | act { 24 | gpios = <&expgpio 2 GPIO_ACTIVE_HIGH>; 25 | }; 26 | }; 27 | 28 | wifi_pwrseq: wifi-pwrseq { 29 | compatible = "mmc-pwrseq-simple"; 30 | reset-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>; 31 | }; 32 | }; 33 | 34 | &firmware { 35 | expgpio: gpio { 36 | compatible = "raspberrypi,firmware-gpio"; 37 | gpio-controller; 38 | #gpio-cells = <2>; 39 | gpio-line-names = "BT_ON", 40 | "WL_ON", 41 | "STATUS_LED", 42 | "LAN_RUN", 43 | "HPD_N", 44 | "CAM_GPIO0", 45 | "CAM_GPIO1", 46 | "PWR_LOW_N"; 47 | status = "okay"; 48 | }; 49 | }; 50 | 51 | &pwm { 52 | pinctrl-names = "default"; 53 | pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>; 54 | status = "okay"; 55 | }; 56 | 57 | &hdmi { 58 | hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>; 59 | }; 60 | 61 | /* uart0 communicates with the BT module */ 62 | &uart0 { 63 | pinctrl-names = "default"; 64 | pinctrl-0 = <&uart0_gpio32 &gpclk2_gpio43>; 65 | status = "okay"; 66 | 67 | bluetooth { 68 | compatible = "brcm,bcm43438-bt"; 69 | max-speed = <2000000>; 70 | shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>; 71 | }; 72 | }; 73 | 74 | /* uart1 is mapped to the pin header */ 75 | &uart1 { 76 | pinctrl-names = "default"; 77 | pinctrl-0 = <&uart1_gpio14>; 78 | status = "okay"; 79 | }; 80 | 81 | /* SDHCI is used to control the SDIO for wireless */ 82 | &sdhci { 83 | #address-cells = <1>; 84 | #size-cells = <0>; 85 | pinctrl-names = "default"; 86 | pinctrl-0 = <&emmc_gpio34>; 87 | status = "okay"; 88 | bus-width = <4>; 89 | non-removable; 90 | mmc-pwrseq = <&wifi_pwrseq>; 91 | 92 | brcmf: wifi@1 { 93 | reg = <1>; 94 | compatible = "brcm,bcm4329-fmac"; 95 | }; 96 | }; 97 | 98 | /* SDHOST is used to drive the SD card */ 99 | &sdhost { 100 | pinctrl-names = "default"; 101 | pinctrl-0 = <&sdhost_gpio48>; 102 | status = "okay"; 103 | bus-width = <4>; 104 | }; 105 | -------------------------------------------------------------------------------- /dts/bcm2837.dtsi: -------------------------------------------------------------------------------- 1 | #include "bcm283x.dtsi" 2 | #include "bcm2835-common.dtsi" 3 | 4 | / { 5 | compatible = "brcm,bcm2837"; 6 | 7 | soc { 8 | ranges = <0x7e000000 0x3f000000 0x1000000>, 9 | <0x40000000 0x40000000 0x00001000>; 10 | dma-ranges = <0xc0000000 0x00000000 0x3f000000>; 11 | 12 | local_intc: local_intc@40000000 { 13 | compatible = "brcm,bcm2836-l1-intc"; 14 | reg = <0x40000000 0x100>; 15 | interrupt-controller; 16 | #interrupt-cells = <2>; 17 | interrupt-parent = <&local_intc>; 18 | }; 19 | }; 20 | 21 | arm-pmu { 22 | compatible = "arm,cortex-a53-pmu"; 23 | interrupt-parent = <&local_intc>; 24 | interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; 25 | }; 26 | 27 | timer { 28 | compatible = "arm,armv7-timer"; 29 | interrupt-parent = <&local_intc>; 30 | interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI 31 | <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI 32 | <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI 33 | <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI 34 | always-on; 35 | }; 36 | 37 | cpus: cpus { 38 | #address-cells = <1>; 39 | #size-cells = <0>; 40 | enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit 41 | 42 | cpu0: cpu@0 { 43 | device_type = "cpu"; 44 | compatible = "arm,cortex-a53"; 45 | reg = <0>; 46 | enable-method = "spin-table"; 47 | cpu-release-addr = <0x0 0x000000d8>; 48 | }; 49 | 50 | cpu1: cpu@1 { 51 | device_type = "cpu"; 52 | compatible = "arm,cortex-a53"; 53 | reg = <1>; 54 | enable-method = "spin-table"; 55 | cpu-release-addr = <0x0 0x000000e0>; 56 | }; 57 | 58 | cpu2: cpu@2 { 59 | device_type = "cpu"; 60 | compatible = "arm,cortex-a53"; 61 | reg = <2>; 62 | enable-method = "spin-table"; 63 | cpu-release-addr = <0x0 0x000000e8>; 64 | }; 65 | 66 | cpu3: cpu@3 { 67 | device_type = "cpu"; 68 | compatible = "arm,cortex-a53"; 69 | reg = <3>; 70 | enable-method = "spin-table"; 71 | cpu-release-addr = <0x0 0x000000f0>; 72 | }; 73 | }; 74 | }; 75 | 76 | /* Make the BCM2835-style global interrupt controller be a child of the 77 | * CPU-local interrupt controller. 78 | */ 79 | &intc { 80 | compatible = "brcm,bcm2836-armctrl-ic"; 81 | reg = <0x7e00b200 0x200>; 82 | interrupt-parent = <&local_intc>; 83 | interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; 84 | }; 85 | 86 | &cpu_thermal { 87 | coefficients = <(-538) 412000>; 88 | }; 89 | 90 | /* enable thermal sensor with the correct compatible property set */ 91 | &thermal { 92 | compatible = "brcm,bcm2837-thermal"; 93 | status = "okay"; 94 | }; 95 | -------------------------------------------------------------------------------- /arm_chainloader/lib_armv6/arm_strlen.s: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 3 | * 4 | * @APPLE_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apple Public Source License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://www.opensource.apple.com/apsl/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPLE_LICENSE_HEADER_END@ 22 | */ 23 | 24 | .text 25 | .align 2 26 | 27 | .globl strlen 28 | /* size_t strlen(const char *s); */ 29 | strlen: 30 | /* save the original pointer */ 31 | mov r12, r0 32 | 33 | /* see if the string is aligned */ 34 | ands r3, r0, #3 35 | 36 | /* load the first word, address rounded down */ 37 | bic r0, r0, #3 38 | ldr r2, [r0], #4 39 | 40 | /* skip the next part if the string is already aligned */ 41 | beq Laligned 42 | 43 | Lunaligned: 44 | /* unaligned pointer, mask out the bytes that we've read that we should be ignoring */ 45 | cmp r3, #2 46 | orr r2, r2, #0x000000ff 47 | orrge r2, r2, #0x0000ff00 48 | orrgt r2, r2, #0x00ff0000 49 | 50 | Laligned: 51 | /* load 0x01010101 into r1 */ 52 | mov r1, #0x01 53 | orr r1, r1, r1, lsl #8 54 | orr r1, r1, r1, lsl #16 55 | 56 | Laligned_loop: 57 | /* ((x - 0x01010101) & ~x & 0x80808080) == hasnull(word) */ 58 | sub r3, r2, r1 /* x - 0x01010101 */ 59 | bic r3, r3, r2 /* above & ~x */ 60 | tst r3, r1, lsl #7 /* above & 0x80808080 */ 61 | ldreq r2, [r0], #4 /* load next word */ 62 | beq Laligned_loop 63 | 64 | /* we found a nullbyte */ 65 | /* r0 (ptr) has overshot by up to 4 bytes, so subtract off until we find a nullbyte */ 66 | sub r0, r0, #1 67 | tst r2, #0x000000ff 68 | subeq r0, r0, #1 69 | tstne r2, #0x0000ff00 70 | subeq r0, r0, #1 71 | tstne r2, #0x00ff0000 72 | subeq r0, r0, #1 73 | 74 | Lexit: 75 | /* len = ptr - original pointer */ 76 | sub r0, r0, r12 77 | bx lr 78 | -------------------------------------------------------------------------------- /nix/sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "haskell.nix": { 3 | "branch": "master", 4 | "description": "Alternative Haskell Infrastructure for Nixpkgs", 5 | "homepage": "https://input-output-hk.github.io/haskell.nix", 6 | "owner": "input-output-hk", 7 | "repo": "haskell.nix", 8 | "rev": "0bc98977a44905a25c45b656af7f29a57a1f2f95", 9 | "sha256": "1cpf23q1pradq5x0qwsc9rdi7l6v0nnb18yv2rb3m3gh8shjann0", 10 | "type": "tarball", 11 | "url": "https://github.com/input-output-hk/haskell.nix/archive/0bc98977a44905a25c45b656af7f29a57a1f2f95.tar.gz", 12 | "url_template": "https://github.com///archive/.tar.gz" 13 | }, 14 | "niv": { 15 | "branch": "master", 16 | "description": "Easy dependency management for Nix projects", 17 | "homepage": "https://github.com/nmattia/niv", 18 | "owner": "nmattia", 19 | "repo": "niv", 20 | "rev": "49157afd2298749b8a5062fd21079542a6b2de35", 21 | "sha256": "0q7ymfrcgagcsw6kr93kprag7k358qj8znyzyri53ci1mrsak5y1", 22 | "type": "tarball", 23 | "url": "https://github.com/nmattia/niv/archive/49157afd2298749b8a5062fd21079542a6b2de35.tar.gz", 24 | "url_template": "https://github.com///archive/.tar.gz" 25 | }, 26 | "nixpkgs": { 27 | "branch": "master", 28 | "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", 29 | "homepage": "https://github.com/nixos/nixpkgs", 30 | "owner": "nixos", 31 | "repo": "nixpkgs", 32 | "rev": "c32264ef79ffeb807015b66fd6c5c893ba1c8ee9", 33 | "sha256": "04p8rra64rhsvkzsdkf9kxibcd8df3wrd1dalcv8ksz8srv7vy34", 34 | "type": "tarball", 35 | "url": "https://github.com/nixos/nixpkgs/archive/c32264ef79ffeb807015b66fd6c5c893ba1c8ee9.tar.gz", 36 | "url_template": "https://github.com///archive/.tar.gz" 37 | }, 38 | "nixpkgs-old": { 39 | "branch": "master", 40 | "description": "Nix Packages collection", 41 | "homepage": null, 42 | "owner": "nixos", 43 | "repo": "nixpkgs", 44 | "rev": "1451a52a38f2dda459647a5c2628e7c28e17c4dc", 45 | "sha256": "15m6xg8y8vbzil374i627ni9dwvsh7p6yz5pbiizmn2h9nj4d57g", 46 | "type": "tarball", 47 | "url": "https://github.com/nixos/nixpkgs/archive/1451a52a38f2dda459647a5c2628e7c28e17c4dc.tar.gz", 48 | "url_template": "https://github.com///archive/.tar.gz" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /arm_chainloader/trap.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * trap.cc 3 | * Copyright (c) 2017 Kristina Brooks 4 | * 5 | * ARM trap handling code. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | struct arm_saved_state { 13 | uint32_t r[13]; /* General purpose register r0-r12 */ 14 | uint32_t sp; /* Stack pointer r13 */ 15 | uint32_t lr; /* Link register r14 */ 16 | uint32_t pc; /* Program counter r15 */ 17 | uint32_t cpsr; /* Current program status register */ 18 | uint32_t fsr; /* Fault status */ 19 | uint32_t far; /* Virtual Fault Address */ 20 | uint32_t exception; /* exception number */ 21 | }; 22 | typedef struct arm_saved_state arm_saved_state_t; 23 | 24 | #define REGISTER_FORMAT_STRING(prefix) \ 25 | prefix " r0: 0x%08lx r1: 0x%08lx r2: 0x%08lx r3: 0x%08lx\n" \ 26 | prefix " r4: 0x%08lx r5: 0x%08lx r6: 0x%08lx r7: 0x%08lx\n" \ 27 | prefix " r8: 0x%08lx r9: 0x%08lx r10: 0x%08lx r11: 0x%08lx\n" \ 28 | prefix " r12: 0x%08lx sp: 0x%08lx lr: 0x%08lx pc: 0x%08lx\n" \ 29 | prefix "cpsr: 0x%08lx\n" 30 | 31 | #define REGISTER_PRINTF_LIST(regs) regs->r[0], regs->r[1], regs->r[2], regs->r[3],\ 32 | regs->r[4], regs->r[5], regs->r[6], regs->r[7], \ 33 | regs->r[8], regs->r[9], regs->r[10], regs->r[11], \ 34 | regs->r[12], regs->sp, regs->lr, regs->pc, regs->cpsr 35 | 36 | extern "C" void fatal_exception(arm_saved_state_t* regs, const char* fmt, ...) 37 | { 38 | va_list va; 39 | 40 | printf("Fatal Exception: "); 41 | va_start(va, fmt); 42 | vprintf(fmt, va); 43 | va_end(va); 44 | printf("\n"); 45 | 46 | printf("ARM registers: \n"); 47 | printf(REGISTER_FORMAT_STRING(" "), REGISTER_PRINTF_LIST(regs)); 48 | 49 | panic("Fatal CPU exception!"); 50 | } 51 | 52 | extern "C" void sleh_undef(arm_saved_state_t* regs) { 53 | fatal_exception(regs, "Undefined instruction"); 54 | } 55 | 56 | extern "C" void sleh_prefabt(arm_saved_state_t* regs) { 57 | fatal_exception(regs, "Prefetch abort"); 58 | } 59 | 60 | extern "C" void sleh_dataabt(arm_saved_state_t* regs) { 61 | uint32_t dfar, dfsr; 62 | __asm__("mrc p15, 0, %0, c6, c0, 0" : "=r"(dfar)); 63 | __asm__("mrc p15, 0, %0, c5, c0, 0" : "=r"(dfsr)); 64 | printf("DFAR: 0x%08lx\nDFSR: 0x%08lx\n", dfar, dfsr); 65 | fatal_exception(regs, "Data abort"); 66 | } 67 | extern "C" void sleh_addrexc(arm_saved_state_t* regs) { 68 | fatal_exception(regs, "Address exception"); 69 | } 70 | 71 | extern "C" void sleh_irq(arm_saved_state_t* regs) { 72 | fatal_exception(regs, "IRQ"); 73 | } 74 | 75 | extern "C" void sleh_fiq(arm_saved_state_t* regs) { 76 | fatal_exception(regs, "FIQ"); 77 | } 78 | -------------------------------------------------------------------------------- /docs/video-pipeline.md: -------------------------------------------------------------------------------- 1 | there are 3 main stages to the video output pipeline in the rpi 2 | 3 | first stage is the [HVS](https://blog.benjdoherty.com/2019/05/21/Exploring-Hardware-Compositing-With-the-Raspberry-Pi/), it will take a display list, convert it into scanlines, and feed them into a FIFO 4 | 5 | second stage is the [pixelvalve](pixelvalve.md), it takes all of the [video timing information](https://wiki.osdev.org/Video_Signals_And_Timing), generates the hsync/vsync pulses, and throttles the flow of pixels from the HVS FIFO to the output PHY 6 | 7 | the third stage is the various output PHY's 8 | * [hdmi](hdmi.md) 9 | * VEC (ntsc/pal video) 10 | * [DPI](https://www.raspberrypi.org/documentation/hardware/raspberrypi/dpi/README.md) 11 | * SMI 12 | * [DSI](https://www.raspberrypi.org/documentation/hardware/display/README.md) 13 | 14 | all pi models have 3 HVS channels, and can drive a total of 3 screens at once (but the official firmware only supports a max of 2) 15 | 16 | VC4 pi's have 3 pixelvalves: 17 | * PV0 can drive DSI0 or DPI 18 | * PV1 can drive DSI1 or SMI 19 | * PV2 can drive HDMI or VEC 20 | 21 | VC6 pi's have 5 pixelvalves: 22 | * PV0 can drive DSI0/DPI 23 | * PV1 can drive DSI1/SMI 24 | * PV2 can drive HDMI0 25 | * PV3 can drive VEC 26 | * PV4 can drive HDMI1 27 | 28 | on VC4, each PV is hard-wired to a certain HVS channel 29 | but on VC6, each PV has a mux to select between any HVS channel(todo, confirm that), but you cant share a channel between 2 PV's 30 | 31 | 32 | ``` 33 | +-----+ +----------+ +----+ +-----+ 34 | | HVS |->| HVS FIFO |->| PV |->| PHY | 35 | +-----+ +----------+ +----+ +-----+ 36 | ``` 37 | 38 | all 3 HVS channels share some FIFO ram, and the `SCALER_DISPBASE[0-2]` registers control which region of the ram each will be using 39 | 40 | some example code: 41 | ``` 42 | hvs_channels[2].dispbase = BASE_BASE(0) | BASE_TOP(0xf00); 43 | hvs_channels[1].dispbase = BASE_BASE(0xf10) | BASE_TOP(0x4b00); 44 | hvs_channels[0].dispbase = BASE_BASE(0x4b10) | BASE_TOP(0x7700); 45 | ``` 46 | under normal conditions, those ranges will have already been configured by the firmware, so the only reason to look at them is to know the latency between the HVS and the PV 47 | 48 | https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/gpu/drm/vc4/vc4_crtc.c#L1136-L1150 49 | 50 | https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/gpu/drm/vc4/vc4_crtc.c#L173-L196 51 | 52 | the lower 12 bits of `SCALER_DISPSTAT[0-2]` say what scanline the HVS is currently on, but based on width and fifo depth, the PV+PHY will be lagging behind a certain number of scanlines 53 | -------------------------------------------------------------------------------- /hs-gpio/PromptString.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NamedFieldPuns #-} 2 | 3 | module PromptString (spawnPromptString) where 4 | 5 | import Brick (EventM, Widget, BrickEvent(VtyEvent), padLeftRight, str, withDefAttr, vBox) 6 | import Brick.Widgets.Center (center) 7 | import qualified Graphics.Vty as V 8 | import qualified Brick.Widgets.Border as B 9 | import Brick.Forms (focusedFormInputAttr, invalidFormInputAttr) 10 | 11 | import Types (Name, DialogReply(DialogReplyContinue), Name, Dialog(dRender, dHandleEvent, Dialog), CustomEvent, AppState) 12 | 13 | data PromptString = PromptString 14 | { psTitle :: String 15 | , psValidator :: String -> Bool 16 | , psCallback :: String -> EventM Name DialogReply 17 | , psCurrentString :: String 18 | } 19 | 20 | spawnPromptString :: String -> (String -> Bool) -> (String -> EventM Name DialogReply) -> EventM Name DialogReply 21 | spawnPromptString title validator callback = do 22 | let 23 | state = PromptString title validator callback "" 24 | pure $ DialogReplyContinue $ mkPromptString state 25 | 26 | mkPromptString :: PromptString -> Dialog 27 | mkPromptString state = Dialog { dRender = renderUI state, dHandleEvent = handleEvents state } 28 | 29 | renderUI :: PromptString -> AppState -> [ Widget Name ] 30 | renderUI PromptString{psCurrentString,psValidator,psTitle} _astate = [ center root ] 31 | where 32 | root :: Widget Name 33 | root = B.borderWithLabel (str psTitle) $ vBox [ pad, padLeftRight 1 $ currentStr, pad ] 34 | attr = if (psValidator psCurrentString) then focusedFormInputAttr else invalidFormInputAttr 35 | currentStr = withDefAttr attr currentStr' 36 | currentStr' = str psCurrentString 37 | pad = str $ replicate (length psTitle) ' ' 38 | 39 | handleEvents :: PromptString -> AppState -> BrickEvent Name CustomEvent -> EventM Name DialogReply 40 | handleEvents pstate@PromptString{psCallback,psCurrentString} _astate event = do 41 | case event of 42 | VtyEvent (V.EvKey V.KEnter []) -> do 43 | -- TODO, allows invalid strings passed to callback 44 | psCallback psCurrentString 45 | VtyEvent (V.EvKey (V.KChar char) []) -> do 46 | pure $ DialogReplyContinue $ mkPromptString $ pstate { psCurrentString = psCurrentString <> [char] } 47 | VtyEvent (V.EvKey V.KBS []) -> do 48 | let 49 | size = length psCurrentString 50 | newstring = take (size - 1) psCurrentString 51 | pure $ DialogReplyContinue $ mkPromptString $ pstate { psCurrentString = newstring } 52 | other -> do 53 | pure $ DialogReplyContinue $ mkPromptString $ pstate { psTitle = show other } 54 | -------------------------------------------------------------------------------- /nixos.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | 3 | let 4 | sources = import ./nix/sources.nix; 5 | self = import ./. {}; 6 | customKernel = pkgs.linux_rpi2.override { 7 | extraConfig = '' 8 | DEBUG_LL y 9 | DEBUG_BCM2836 y 10 | DEBUG_UART_PL01X y 11 | DEBUG_UNCOMPRESS y 12 | EARLY_PRINTK y 13 | RASPBERRYPI_FIRMWARE n 14 | ''; 15 | }; 16 | customKernelPackages = pkgs.linuxPackagesFor customKernel; 17 | in { 18 | imports = [ 19 | (sources.nixpkgs + "/nixos/modules/profiles/minimal.nix") 20 | ./bootloader.nix 21 | ]; 22 | environment = { 23 | systemPackages = [ 24 | self.arm7.hs.hs-gpio.cexes.hs-gpio 25 | pkgs.i2c-tools 26 | pkgs.screen 27 | pkgs.ncdu 28 | pkgs.usbutils 29 | self.arm7.utils 30 | pkgs.dtc 31 | #pkgs.gdb 32 | ]; 33 | etc.busybox.source = pkgs.busybox; 34 | }; 35 | nixpkgs = { 36 | crossSystem.system = "armv7l-linux"; 37 | overlays = [ 38 | (self: super: { 39 | libgpgerror = self.callPackage "${sources.nixpkgs-old}/pkgs/development/libraries/libgpg-error/default.nix" {}; 40 | }) 41 | ]; 42 | }; 43 | networking = { 44 | useDHCP = false; 45 | interfaces.eth0.useDHCP = true; 46 | nameservers = [ "192.168.2.1" ]; 47 | firewall.enable = false; 48 | }; 49 | boot = { 50 | kernelPackages = customKernelPackages; 51 | kernelParams = [ 52 | "print-fatal-signals=1" 53 | "console=ttyAMA0,115200" 54 | "earlyprintk" 55 | "printk.devkmsg=on" 56 | "boot.shell_on_fail" 57 | ''dyndbg="file bcm2835-mailbox.c +p"'' 58 | "iomem=relaxed" 59 | ]; 60 | loader = { 61 | grub.enable = false; 62 | openpi = { 63 | enable = true; 64 | }; 65 | }; 66 | }; 67 | fonts.fontconfig.enable = false; 68 | security.polkit.enable = false; 69 | security.rngd.enable = false; 70 | services = { 71 | udisks2.enable = lib.mkForce false; 72 | openssh.enable = true; 73 | ntp.enable = false; # cross-compile breaks it 74 | avahi.enable = true; 75 | prometheus.exporters.node.enable = true; 76 | }; 77 | programs.bash.enableCompletion = false; 78 | users.users.root = { 79 | openssh.authorizedKeys.keys = [ 80 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC34wZQFEOGkA5b0Z6maE3aKy/ix1MiK1D0Qmg4E9skAA57yKtWYzjA23r5OCF4Nhlj1CuYd6P1sEI/fMnxf+KkqqgW3ZoZ0+pQu4Bd8Ymi3OkkQX9kiq2coD3AFI6JytC6uBi6FaZQT5fG59DbXhxO5YpZlym8ps1obyCBX0hyKntD18RgHNaNM+jkQOhQ5OoxKsBEobxQOEdjIowl2QeEHb99n45sFr53NFqk3UCz0Y7ZMf1hSFQPuuEC/wExzBBJ1Wl7E1LlNA4p9O3qJUSadGZS4e5nSLqMnbQWv2icQS/7J8IwY0M8r1MsL8mdnlXHUofPlG1r4mtovQ2myzOx clever@nixos" 81 | ]; 82 | }; 83 | } 84 | --------------------------------------------------------------------------------