├── .github └── workflows │ └── heads-ubuntu.yml ├── .gitignore ├── Makefile ├── README.md ├── config ├── busybox.config ├── coreboot-qemu.config ├── coreboot-x230.config ├── initrd-base.config ├── linux-virtio.config └── linux-x230.config ├── cpiofile.py ├── heads-builder.py ├── helloworld.py ├── init.c ├── initrd-builder ├── jump-builder.py ├── linux-builder ├── localcompile.py ├── modules ├── busybox ├── cairo ├── cryptsetup ├── cryptsetup2 ├── dropbear ├── fbwhiptail ├── flashrom ├── iasl ├── json-c ├── kexec ├── libpng ├── lvm2 ├── newt ├── openssh ├── openssl ├── pciutils ├── pixman ├── popt ├── slang ├── util-linux └── zlib ├── patches ├── acpica-unix2-20210331_iasl.patch ├── cairo-1.14.12.patch ├── coreboot-4.13 │ ├── 0010-genbuild-iasl.patch │ ├── 0020-ld-nostartfiles.patch │ └── 0080-util-crossgcc-builgcc_temp_fix_from_https_to_http.patch ├── coreboot-4.15 │ ├── 0001-soc-skylake-me.c-Print-status-regardless-of-device-e.patch │ ├── 0002-soc-cannonlake-me.c-Print-status-regardless-of-devic.patch │ ├── 0003-soc-intel-cannonlake-Add-PcieRpHotPlug-config-to-FSP.patch │ ├── 0004-soc-intel-skylake-move-heci_init-from-bootblock-to-r.patch │ ├── 0005-soc-intel-common-cse-Drop-CSE-library-usage-in-bootb.patch │ ├── 0006-soc-intel-common-cse-skip-heci_init-if-HECI1-is-disa.patch │ ├── 0007-mb-purism-librem_skl-disable-HECI-PCI-device.patch │ ├── 0008-makefile-opt-libs.patch │ ├── 0009-rcba_pirq-printk.patch │ └── 0010-genbuild-iasl.patch ├── cryptsetup-1.7.3.patch ├── dropbear-2016.74.patch ├── fbwhiptail.patch ├── flashrom-0100-enable-kgpe-d16.patch ├── kexec-2.0.20-duplicate-symbols.patch ├── kexec-2.0.20.patch ├── linux-4.14.62 │ ├── 0000-efi_bds.patch │ ├── 0001-fake-acpi.patch │ ├── 0002-nmi-squelch.patch │ ├── 0003-fake-trampoline.patch │ ├── 0010-winterfell-ahci.patch │ └── 0020-missing-symboltable.patch ├── lvm2-2.02.168 │ ├── 0010-misc.patch │ └── 0020-sort-wildcard.patch ├── musl-1.2.2 │ ├── 0010-fastmath.patch │ └── 0020-relative-paths.patch └── pciutils-3.5.4.patch ├── unify-kernel └── worldbuilder ├── __init__.py ├── builder.py ├── commands.py ├── coreboot.py ├── crosscompile.py ├── graphlib_backport.py ├── initrd.py ├── linux.py ├── submodule.py └── util.py /.github/workflows/heads-ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Build heads firmware on ubuntu 20.04 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | build: 9 | name: Build package 10 | runs-on: ubuntu-latest 11 | container: 12 | image: 'ubuntu:20.04' 13 | steps: 14 | - name: Checkout master 15 | uses: actions/checkout@v1 16 | 17 | - name: Update image 18 | run: apt update 19 | - name: Install dependencies 20 | run: DEBIAN_FRONTEND=noninteractive apt install -y patch gcc g++ python3 python3-pip python3-requests git texinfo bzip2 xz-utils cmake bc lz4 libssl-dev flex bison m4 rsync wget libelf-dev 21 | - name: Build package 22 | run: SINGLE_THREAD=1 CACHE_SERVER=https://v.st/~hudson/cache make -j3 heads 23 | 24 | - name: Upload built coreboot packages 25 | uses: actions/upload-artifact@v3 26 | with: 27 | name: images 28 | path: | 29 | build/install/coreboot-*/*/coreboot-*.rom 30 | build/install/initrd-*/*/*.hashes 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .*.cmd 3 | Module.symvers 4 | *.o 5 | *.a 6 | modules.order 7 | *.ko 8 | *.mod 9 | *.mod.c 10 | build 11 | kernel/linux* 12 | *.sign 13 | *.xz 14 | .*.d 15 | tags 16 | ctags 17 | *.bin 18 | *.efi 19 | *.exe 20 | *.img 21 | *.iso 22 | *.fd 23 | *.tar.gz 24 | init 25 | __pycache__ 26 | *.log 27 | *.cpio 28 | *.hashes 29 | lib*.so.* 30 | a.out 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: init 2 | init: init.c 3 | $(CC) -O3 -W -Wall -o $@ $< 4 | 5 | world: 6 | +./helloworld.py 7 | heads: 8 | +./heads-builder.py 9 | 10 | jump: 11 | +./jump-builder.py 12 | 13 | %: 14 | +./heads-builder.py $@ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linux Appliance Builder 2 | 3 | These scripts are useful for building Linux appliances or firmware images that 4 | do not require a full user-land and have a custom kernel configuration with 5 | optional patches. It also has a script to build a unified kernel image with 6 | the initrd and command line in a signed EFI application. 7 | 8 | ## linux-builder 9 | 10 | To use, start with a `linux.config` file and run: 11 | 12 | ``` 13 | linux-builder \ 14 | -v \ 15 | --version 5.4.117 \ 16 | --config linux.config 17 | ``` 18 | 19 | This will download Linux 5.4.117 from kernel.org, (todo verify it), 20 | unpack it, apply any patches, generate the `.config` file for it 21 | and then invoke a recursive `make` to build it in `./build`. 22 | 23 | ## initrd-builder 24 | 25 | For the kernel's initial ramdisk cpio file, you might be able to just 26 | list the binaries that you want to include and then: 27 | 28 | ``` 29 | initrd-builder \ 30 | -v \ 31 | -o build/initrd.cpio.xz \ 32 | base-initrd.conf \ 33 | my-initrd.conf 34 | ``` 35 | 36 | ## unify-kernel 37 | 38 | ``` 39 | unify-kernel \ 40 | --kernel build/vmlinuz-linux \ 41 | --initrd build/initrd.cpio.xz \ 42 | --commandline commandline.txt \ 43 | -o build/bootx64.efi 44 | ``` 45 | 46 | 47 | 48 | ---- 49 | 50 | # worldbuilder 51 | 52 | `worldbuilder` uses Python3 (> 3.9), make and patch, 53 | various autotools need flex/bison/m4, 54 | `json-c` uses cmake, 55 | `openssl` uses some Perl packages. 56 | linux kernel wants rsync, bc, lz4, and host-side tools need openssl 57 | 58 | Fedora requirements: 59 | ``` 60 | dnf install \ 61 | make patch gcc g++ python3 git \ 62 | texinfo \ 63 | bzip2 xz \ 64 | cmake \ 65 | perl-FindBin perl-File-Compare \ 66 | bc lz4 openssl-devel \ 67 | flex bison m4 elfutils-libelf-devel 68 | ``` 69 | 70 | Debian requirements: 71 | ``` 72 | apt install \ 73 | make patch gcc g++ python3 git \ 74 | texinfo \ 75 | bzip2 xz-utils \ 76 | cmake \ 77 | bc lz4 libssl-dev flex bison m4 rsync libelf-dev 78 | ``` 79 | 80 | ``` 81 | git clone https://github.com/osresearch/linux-builder 82 | cd linux-builder 83 | make -j64 heads 84 | ``` 85 | 86 | 87 | TODO: can we remove the texinfo requirement? 88 | TODO: can we reduce the @development-tools to just gcc? 89 | 90 | -------------------------------------------------------------------------------- /config/coreboot-qemu.config: -------------------------------------------------------------------------------- 1 | # CONFIG_INCLUDE_CONFIG_FILE is not set 2 | CONFIG_CBFS_SIZE=0x750000 3 | # CONFIG_POST_IO is not set 4 | # CONFIG_POST_DEVICE is not set 5 | CONFIG_BOARD_EMULATION_QEMU_X86_Q35=y 6 | # CONFIG_CONSOLE_SERIAL is not set 7 | CONFIG_LINUX_COMMAND_LINE="debug console=ttyS0 vga=786" 8 | CONFIG_COREBOOT_ROMSIZE_KB_8192=y 9 | CONFIG_PCIEXP_ASPM=y 10 | CONFIG_PCIEXP_COMMON_CLOCK=y 11 | CONFIG_UART_PCI_ADDR=0 12 | CONFIG_DRIVERS_PS2_KEYBOARD=y 13 | CONFIG_DEFAULT_CONSOLE_LOGLEVEL_6=y 14 | CONFIG_PAYLOAD_LINUX=y 15 | CONFIG_ANY_TOOLCHAIN=y 16 | -------------------------------------------------------------------------------- /config/coreboot-x230.config: -------------------------------------------------------------------------------- 1 | # CONFIG_USE_BLOBS is not set 2 | CONFIG_VENDOR_LENOVO=y 3 | CONFIG_NO_POST=y 4 | CONFIG_CBFS_SIZE=0x700000 5 | CONFIG_BOARD_LENOVO_X230=y 6 | CONFIG_LINUX_COMMAND_LINE="intel_iommu=igfx_off quiet" 7 | CONFIG_UART_PCI_ADDR=0 8 | CONFIG_NO_GFX_INIT=y 9 | CONFIG_DRIVERS_PS2_KEYBOARD=y 10 | CONFIG_CPU_MICROCODE_CBFS_NONE=y 11 | CONFIG_TPM_MEASURED_BOOT=y 12 | CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x80000 13 | CONFIG_PAYLOAD_LINUX=y 14 | #CONFIG_PAYLOAD_FILE="../../build/x230/bzImage" 15 | #CONFIG_LINUX_INITRD="../../build/x230/initrd.cpio.xz" 16 | CONFIG_ANY_TOOLCHAIN=y 17 | -------------------------------------------------------------------------------- /config/initrd-base.config: -------------------------------------------------------------------------------- 1 | # console device file is necessary to boot 2 | mkdir /dev 3 | mknod /dev/console c 5 1 4 | 5 | # libraries go into /lib64, although some rpath 6 | # refer to the alternate directory instead 7 | mkdir /lib64 8 | mkdir /lib 9 | symlink ../lib64 lib/x86_64-linux-gnu 10 | 11 | mkdir /tmp 12 | -------------------------------------------------------------------------------- /config/linux-virtio.config: -------------------------------------------------------------------------------- 1 | # CONFIG_LOCALVERSION_AUTO is not set 2 | CONFIG_KERNEL_LZ4=y 3 | CONFIG_DEFAULT_HOSTNAME="qemu-linux" 4 | # CONFIG_CROSS_MEMORY_ATTACH is not set 5 | CONFIG_HIGH_RES_TIMERS=y 6 | CONFIG_TASKSTATS=y 7 | CONFIG_TASK_DELAY_ACCT=y 8 | CONFIG_BLK_DEV_INITRD=y 9 | # CONFIG_RD_GZIP is not set 10 | # CONFIG_RD_LZMA is not set 11 | # CONFIG_RD_LZO is not set 12 | # CONFIG_RD_LZ4 is not set 13 | # CONFIG_SGETMASK_SYSCALL is not set 14 | # CONFIG_SYSFS_SYSCALL is not set 15 | # CONFIG_FHANDLE is not set 16 | # CONFIG_BUG is not set 17 | # CONFIG_PCSPKR_PLATFORM is not set 18 | # CONFIG_BASE_FULL is not set 19 | # CONFIG_TIMERFD is not set 20 | # CONFIG_AIO is not set 21 | # CONFIG_IO_URING is not set 22 | # CONFIG_MEMBARRIER is not set 23 | # CONFIG_KALLSYMS is not set 24 | # CONFIG_RSEQ is not set 25 | CONFIG_EMBEDDED=y 26 | # CONFIG_VM_EVENT_COUNTERS is not set 27 | # CONFIG_COMPAT_BRK is not set 28 | CONFIG_SLOB=y 29 | # CONFIG_SLAB_MERGE_DEFAULT is not set 30 | # CONFIG_ZONE_DMA is not set 31 | CONFIG_SMP=y 32 | # CONFIG_X86_EXTENDED_PLATFORM is not set 33 | # CONFIG_SCHED_OMIT_FRAME_POINTER is not set 34 | CONFIG_HYPERVISOR_GUEST=y 35 | CONFIG_PROCESSOR_SELECT=y 36 | # CONFIG_DMI is not set 37 | # CONFIG_SCHED_MC_PRIO is not set 38 | # CONFIG_X86_MCE is not set 39 | # CONFIG_X86_VSYSCALL_EMULATION is not set 40 | # CONFIG_MICROCODE is not set 41 | CONFIG_X86_MSR=y 42 | # CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set 43 | # CONFIG_SECCOMP is not set 44 | CONFIG_HZ_100=y 45 | CONFIG_CMDLINE_BOOL=y 46 | CONFIG_CMDLINE="console=hvc0" 47 | # CONFIG_MODIFY_LDT_SYSCALL is not set 48 | # CONFIG_SUSPEND is not set 49 | # CONFIG_ACPI is not set 50 | # CONFIG_ISA_DMA_API is not set 51 | # CONFIG_VIRTUALIZATION is not set 52 | CONFIG_JUMP_LABEL=y 53 | # CONFIG_BLOCK is not set 54 | # CONFIG_COREDUMP is not set 55 | CONFIG_TRANSPARENT_HUGEPAGE=y 56 | CONFIG_NET=y 57 | CONFIG_PACKET=y 58 | CONFIG_UNIX=y 59 | CONFIG_INET=y 60 | CONFIG_IP_MULTICAST=y 61 | CONFIG_IP_PNP=y 62 | CONFIG_IP_PNP_DHCP=y 63 | CONFIG_SYN_COOKIES=y 64 | # CONFIG_INET_DIAG is not set 65 | # CONFIG_IPV6 is not set 66 | CONFIG_VLAN_8021Q=y 67 | # CONFIG_WIRELESS is not set 68 | CONFIG_PCI=y 69 | CONFIG_DEVTMPFS=y 70 | # CONFIG_STANDALONE is not set 71 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set 72 | # CONFIG_FW_LOADER is not set 73 | # CONFIG_ALLOW_DEV_COREDUMP is not set 74 | CONFIG_NETDEVICES=y 75 | CONFIG_VIRTIO_NET=y 76 | # CONFIG_NET_VENDOR_3COM is not set 77 | # CONFIG_NET_VENDOR_ADAPTEC is not set 78 | # CONFIG_NET_VENDOR_AGERE is not set 79 | # CONFIG_NET_VENDOR_ALACRITECH is not set 80 | # CONFIG_NET_VENDOR_ALTEON is not set 81 | # CONFIG_NET_VENDOR_AMAZON is not set 82 | # CONFIG_NET_VENDOR_AMD is not set 83 | # CONFIG_NET_VENDOR_AQUANTIA is not set 84 | # CONFIG_NET_VENDOR_ARC is not set 85 | # CONFIG_NET_VENDOR_ATHEROS is not set 86 | # CONFIG_NET_VENDOR_AURORA is not set 87 | # CONFIG_NET_VENDOR_BROADCOM is not set 88 | # CONFIG_NET_VENDOR_BROCADE is not set 89 | # CONFIG_NET_VENDOR_CADENCE is not set 90 | # CONFIG_NET_VENDOR_CAVIUM is not set 91 | # CONFIG_NET_VENDOR_CHELSIO is not set 92 | # CONFIG_NET_VENDOR_CISCO is not set 93 | # CONFIG_NET_VENDOR_CORTINA is not set 94 | # CONFIG_NET_VENDOR_DEC is not set 95 | # CONFIG_NET_VENDOR_DLINK is not set 96 | # CONFIG_NET_VENDOR_EMULEX is not set 97 | # CONFIG_NET_VENDOR_EZCHIP is not set 98 | # CONFIG_NET_VENDOR_GOOGLE is not set 99 | # CONFIG_NET_VENDOR_HP is not set 100 | # CONFIG_NET_VENDOR_HUAWEI is not set 101 | # CONFIG_NET_VENDOR_INTEL is not set 102 | # CONFIG_NET_VENDOR_MARVELL is not set 103 | # CONFIG_NET_VENDOR_MELLANOX is not set 104 | # CONFIG_NET_VENDOR_MICREL is not set 105 | # CONFIG_NET_VENDOR_MICROCHIP is not set 106 | # CONFIG_NET_VENDOR_MICROSEMI is not set 107 | # CONFIG_NET_VENDOR_MYRI is not set 108 | # CONFIG_NET_VENDOR_NATSEMI is not set 109 | # CONFIG_NET_VENDOR_NETERION is not set 110 | # CONFIG_NET_VENDOR_NETRONOME is not set 111 | # CONFIG_NET_VENDOR_NI is not set 112 | # CONFIG_NET_VENDOR_NVIDIA is not set 113 | # CONFIG_NET_VENDOR_OKI is not set 114 | # CONFIG_NET_VENDOR_PACKET_ENGINES is not set 115 | # CONFIG_NET_VENDOR_PENSANDO is not set 116 | # CONFIG_NET_VENDOR_QLOGIC is not set 117 | # CONFIG_NET_VENDOR_QUALCOMM is not set 118 | # CONFIG_NET_VENDOR_RDC is not set 119 | # CONFIG_NET_VENDOR_REALTEK is not set 120 | # CONFIG_NET_VENDOR_RENESAS is not set 121 | # CONFIG_NET_VENDOR_ROCKER is not set 122 | # CONFIG_NET_VENDOR_SAMSUNG is not set 123 | # CONFIG_NET_VENDOR_SEEQ is not set 124 | # CONFIG_NET_VENDOR_SOLARFLARE is not set 125 | # CONFIG_NET_VENDOR_SILAN is not set 126 | # CONFIG_NET_VENDOR_SIS is not set 127 | # CONFIG_NET_VENDOR_SMSC is not set 128 | # CONFIG_NET_VENDOR_SOCIONEXT is not set 129 | # CONFIG_NET_VENDOR_STMICRO is not set 130 | # CONFIG_NET_VENDOR_SUN is not set 131 | # CONFIG_NET_VENDOR_SYNOPSYS is not set 132 | # CONFIG_NET_VENDOR_TEHUTI is not set 133 | # CONFIG_NET_VENDOR_TI is not set 134 | # CONFIG_NET_VENDOR_VIA is not set 135 | # CONFIG_NET_VENDOR_WIZNET is not set 136 | # CONFIG_NET_VENDOR_XILINX is not set 137 | # CONFIG_WLAN is not set 138 | # CONFIG_INPUT_KEYBOARD is not set 139 | # CONFIG_INPUT_MOUSE is not set 140 | # CONFIG_SERIO is not set 141 | CONFIG_SERIAL_8250=y 142 | # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set 143 | CONFIG_SERIAL_8250_CONSOLE=y 144 | # CONFIG_SERIAL_8250_PCI is not set 145 | # CONFIG_SERIAL_8250_LPSS is not set 146 | # CONFIG_SERIAL_8250_MID is not set 147 | CONFIG_TTY_PRINTK=y 148 | CONFIG_VIRTIO_CONSOLE=y 149 | # CONFIG_HW_RANDOM_INTEL is not set 150 | # CONFIG_HW_RANDOM_AMD is not set 151 | # CONFIG_HW_RANDOM_VIA is not set 152 | CONFIG_HW_RANDOM_VIRTIO=y 153 | CONFIG_NVRAM=y 154 | CONFIG_TCG_TPM=y 155 | CONFIG_TCG_TIS=y 156 | CONFIG_RANDOM_TRUST_CPU=y 157 | CONFIG_RANDOM_TRUST_BOOTLOADER=y 158 | CONFIG_I2C=y 159 | CONFIG_PTP_1588_CLOCK=y 160 | # CONFIG_HWMON is not set 161 | # CONFIG_VGA_ARB is not set 162 | # CONFIG_VGA_CONSOLE is not set 163 | # CONFIG_HID is not set 164 | # CONFIG_USB_SUPPORT is not set 165 | CONFIG_SYNC_FILE=y 166 | CONFIG_VIRTIO_PCI=y 167 | CONFIG_VIRTIO_INPUT=y 168 | # CONFIG_X86_PLATFORM_DEVICES is not set 169 | # CONFIG_IOMMU_SUPPORT is not set 170 | # CONFIG_DNOTIFY is not set 171 | # CONFIG_INOTIFY_USER is not set 172 | CONFIG_TMPFS=y 173 | CONFIG_HUGETLBFS=y 174 | # CONFIG_MISC_FILESYSTEMS is not set 175 | # CONFIG_NETWORK_FILESYSTEMS is not set 176 | CONFIG_KEYS=y 177 | CONFIG_SECURITY=y 178 | CONFIG_FORTIFY_SOURCE=y 179 | CONFIG_SECURITY_LOCKDOWN_LSM=y 180 | CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y 181 | CONFIG_CRYPTO_RSA=y 182 | CONFIG_CRYPTO_CBC=y 183 | CONFIG_CRYPTO_XTS=y 184 | CONFIG_CRYPTO_ESSIV=y 185 | CONFIG_CRYPTO_HMAC=y 186 | CONFIG_CRYPTO_CRC32C=y 187 | CONFIG_CRYPTO_MD5=y 188 | CONFIG_CRYPTO_SHA1_SSSE3=y 189 | CONFIG_CRYPTO_SHA256_SSSE3=y 190 | CONFIG_CRYPTO_AES=y 191 | CONFIG_CRYPTO_AES_NI_INTEL=y 192 | CONFIG_ASYMMETRIC_KEY_TYPE=y 193 | CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y 194 | CONFIG_X509_CERTIFICATE_PARSER=y 195 | CONFIG_PKCS7_MESSAGE_PARSER=y 196 | CONFIG_SYSTEM_TRUSTED_KEYRING=y 197 | CONFIG_CRC16=y 198 | CONFIG_CRC_ITU_T=y 199 | CONFIG_IRQ_POLL=y 200 | CONFIG_PRINTK_TIME=y 201 | CONFIG_FRAME_WARN=1024 202 | # CONFIG_SECTION_MISMATCH_WARN_ONLY is not set 203 | # CONFIG_DEBUG_MISC is not set 204 | # CONFIG_FTRACE is not set 205 | # CONFIG_RUNTIME_TESTING_MENU is not set 206 | # CONFIG_STRICT_DEVMEM is not set 207 | # CONFIG_X86_VERBOSE_BOOTUP is not set 208 | # CONFIG_X86_DEBUG_FPU is not set 209 | CONFIG_UNWINDER_GUESS=y 210 | -------------------------------------------------------------------------------- /config/linux-x230.config: -------------------------------------------------------------------------------- 1 | CONFIG_LOCALVERSION="-heads" 2 | # CONFIG_LOCALVERSION_AUTO is not set 3 | CONFIG_KERNEL_XZ=y 4 | # CONFIG_SWAP is not set 5 | # CONFIG_CROSS_MEMORY_ATTACH is not set 6 | # CONFIG_FHANDLE is not set 7 | CONFIG_NO_HZ_IDLE=y 8 | CONFIG_LOG_BUF_SHIFT=18 9 | CONFIG_BLK_DEV_INITRD=y 10 | CONFIG_INITRAMFS_SOURCE="../../../blobs/dev.cpio" 11 | # CONFIG_RD_GZIP is not set 12 | # CONFIG_RD_BZIP2 is not set 13 | # CONFIG_RD_LZMA is not set 14 | # CONFIG_RD_LZO is not set 15 | # CONFIG_RD_LZ4 is not set 16 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y 17 | # CONFIG_SGETMASK_SYSCALL is not set 18 | # CONFIG_SYSFS_SYSCALL is not set 19 | # CONFIG_BASE_FULL is not set 20 | # CONFIG_SIGNALFD is not set 21 | # CONFIG_TIMERFD is not set 22 | # CONFIG_EVENTFD is not set 23 | # CONFIG_AIO is not set 24 | # CONFIG_ADVISE_SYSCALLS is not set 25 | # CONFIG_MEMBARRIER is not set 26 | CONFIG_EMBEDDED=y 27 | # CONFIG_VM_EVENT_COUNTERS is not set 28 | # CONFIG_SLUB_DEBUG is not set 29 | # CONFIG_COMPAT_BRK is not set 30 | CONFIG_JUMP_LABEL=y 31 | CONFIG_CC_STACKPROTECTOR_STRONG=y 32 | CONFIG_MODULES=y 33 | # CONFIG_IOSCHED_DEADLINE is not set 34 | # CONFIG_IOSCHED_CFQ is not set 35 | CONFIG_SMP=y 36 | # CONFIG_X86_EXTENDED_PLATFORM is not set 37 | CONFIG_PROCESSOR_SELECT=y 38 | # CONFIG_CPU_SUP_CENTAUR is not set 39 | CONFIG_PREEMPT_VOLUNTARY=y 40 | CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y 41 | # CONFIG_X86_MCE_AMD is not set 42 | # CONFIG_PERF_EVENTS_INTEL_RAPL is not set 43 | # CONFIG_MICROCODE is not set 44 | # CONFIG_SPARSEMEM_VMEMMAP is not set 45 | # CONFIG_COMPACTION is not set 46 | # CONFIG_BOUNCE is not set 47 | CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 48 | CONFIG_X86_PMEM_LEGACY=y 49 | # CONFIG_MTRR is not set 50 | # CONFIG_X86_SMAP is not set 51 | # CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS is not set 52 | # CONFIG_SECCOMP is not set 53 | CONFIG_KEXEC=y 54 | CONFIG_KEXEC_FILE=y 55 | # CONFIG_RELOCATABLE is not set 56 | CONFIG_PHYSICAL_ALIGN=0x1000000 57 | # CONFIG_MODIFY_LDT_SYSCALL is not set 58 | # CONFIG_SUSPEND is not set 59 | CONFIG_ACPI_VIDEO=y 60 | CONFIG_PCI_MSI=y 61 | # CONFIG_HT_IRQ is not set 62 | CONFIG_PCI_IOV=y 63 | CONFIG_PCI_PRI=y 64 | # CONFIG_COREDUMP is not set 65 | CONFIG_NET=y 66 | CONFIG_PACKET=y 67 | CONFIG_UNIX=y 68 | CONFIG_INET=y 69 | CONFIG_SYN_COOKIES=y 70 | # CONFIG_INET_XFRM_MODE_TRANSPORT is not set 71 | # CONFIG_INET_XFRM_MODE_TUNNEL is not set 72 | # CONFIG_INET_XFRM_MODE_BEET is not set 73 | # CONFIG_INET_DIAG is not set 74 | # CONFIG_IPV6 is not set 75 | # CONFIG_WIRELESS is not set 76 | # CONFIG_UEVENT_HELPER is not set 77 | CONFIG_DEVTMPFS=y 78 | CONFIG_DEVTMPFS_MOUNT=y 79 | # CONFIG_STANDALONE is not set 80 | # CONFIG_FIRMWARE_IN_KERNEL is not set 81 | # CONFIG_ALLOW_DEV_COREDUMP is not set 82 | CONFIG_BLK_DEV_LOOP=y 83 | CONFIG_BLK_DEV_RAM=y 84 | CONFIG_BLK_DEV_RAM_SIZE=65536 85 | CONFIG_EEPROM_93CX6=m 86 | CONFIG_INTEL_MEI_ME=m 87 | CONFIG_INTEL_MEI_TXE=m 88 | # CONFIG_SCSI_PROC_FS is not set 89 | CONFIG_BLK_DEV_SD=y 90 | CONFIG_BLK_DEV_SR=y 91 | CONFIG_CHR_DEV_SG=y 92 | CONFIG_SCSI_SCAN_ASYNC=y 93 | CONFIG_ISCSI_TCP=y 94 | CONFIG_ATA=y 95 | CONFIG_SATA_AHCI=y 96 | # CONFIG_ATA_SFF is not set 97 | CONFIG_MD=y 98 | CONFIG_BLK_DEV_DM=y 99 | CONFIG_DM_CRYPT=y 100 | CONFIG_DM_VERITY=y 101 | CONFIG_DM_VERITY_FEC=y 102 | CONFIG_NETDEVICES=y 103 | # CONFIG_NET_VENDOR_3COM is not set 104 | # CONFIG_NET_VENDOR_ADAPTEC is not set 105 | # CONFIG_NET_VENDOR_AGERE is not set 106 | # CONFIG_NET_VENDOR_ALTEON is not set 107 | # CONFIG_NET_VENDOR_AMAZON is not set 108 | # CONFIG_NET_VENDOR_AMD is not set 109 | # CONFIG_NET_VENDOR_ARC is not set 110 | # CONFIG_NET_VENDOR_ATHEROS is not set 111 | # CONFIG_NET_CADENCE is not set 112 | # CONFIG_NET_VENDOR_BROADCOM is not set 113 | # CONFIG_NET_VENDOR_BROCADE is not set 114 | # CONFIG_NET_VENDOR_CAVIUM is not set 115 | # CONFIG_NET_VENDOR_CHELSIO is not set 116 | # CONFIG_NET_VENDOR_CISCO is not set 117 | # CONFIG_NET_VENDOR_DEC is not set 118 | # CONFIG_NET_VENDOR_DLINK is not set 119 | # CONFIG_NET_VENDOR_EMULEX is not set 120 | # CONFIG_NET_VENDOR_EZCHIP is not set 121 | # CONFIG_NET_VENDOR_EXAR is not set 122 | # CONFIG_NET_VENDOR_HP is not set 123 | CONFIG_E1000=m 124 | CONFIG_E1000E=m 125 | # CONFIG_NET_VENDOR_I825XX is not set 126 | # CONFIG_NET_VENDOR_MARVELL is not set 127 | # CONFIG_NET_VENDOR_MELLANOX is not set 128 | # CONFIG_NET_VENDOR_MICREL is not set 129 | # CONFIG_NET_VENDOR_MYRI is not set 130 | # CONFIG_NET_VENDOR_NATSEMI is not set 131 | # CONFIG_NET_VENDOR_NETRONOME is not set 132 | # CONFIG_NET_VENDOR_NVIDIA is not set 133 | # CONFIG_NET_VENDOR_OKI is not set 134 | # CONFIG_NET_PACKET_ENGINE is not set 135 | # CONFIG_NET_VENDOR_QLOGIC is not set 136 | # CONFIG_NET_VENDOR_QUALCOMM is not set 137 | # CONFIG_NET_VENDOR_REALTEK is not set 138 | # CONFIG_NET_VENDOR_RENESAS is not set 139 | # CONFIG_NET_VENDOR_RDC is not set 140 | # CONFIG_NET_VENDOR_ROCKER is not set 141 | # CONFIG_NET_VENDOR_SAMSUNG is not set 142 | # CONFIG_NET_VENDOR_SEEQ is not set 143 | # CONFIG_NET_VENDOR_SILAN is not set 144 | # CONFIG_NET_VENDOR_SIS is not set 145 | # CONFIG_NET_VENDOR_SMSC is not set 146 | # CONFIG_NET_VENDOR_STMICRO is not set 147 | # CONFIG_NET_VENDOR_SUN is not set 148 | # CONFIG_NET_VENDOR_TEHUTI is not set 149 | # CONFIG_NET_VENDOR_TI is not set 150 | # CONFIG_NET_VENDOR_VIA is not set 151 | # CONFIG_NET_VENDOR_WIZNET is not set 152 | # CONFIG_NET_VENDOR_SYNOPSYS is not set 153 | # CONFIG_USB_NET_DRIVERS is not set 154 | # CONFIG_WLAN is not set 155 | # CONFIG_INPUT_MOUSE is not set 156 | # CONFIG_SERIO_SERPORT is not set 157 | # CONFIG_UNIX98_PTYS is not set 158 | # CONFIG_LEGACY_PTYS is not set 159 | CONFIG_SERIAL_8250=y 160 | # CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set 161 | # CONFIG_SERIAL_8250_PNP is not set 162 | # CONFIG_SERIAL_8250_PCI is not set 163 | # CONFIG_SERIAL_8250_LPSS is not set 164 | # CONFIG_SERIAL_8250_MID is not set 165 | CONFIG_TTY_PRINTK=y 166 | CONFIG_HW_RANDOM=y 167 | CONFIG_HW_RANDOM_TIMERIOMEM=m 168 | CONFIG_HW_RANDOM_INTEL=m 169 | CONFIG_HW_RANDOM_AMD=m 170 | CONFIG_HW_RANDOM_VIA=m 171 | CONFIG_HW_RANDOM_TPM=m 172 | CONFIG_TCG_TPM=y 173 | CONFIG_TCG_TIS=y 174 | # CONFIG_I2C_COMPAT is not set 175 | CONFIG_I2C_MUX=m 176 | CONFIG_I2C_MUX_PCA9541=m 177 | CONFIG_I2C_MUX_REG=m 178 | # CONFIG_I2C_HELPER_AUTO is not set 179 | CONFIG_I2C_SLAVE=y 180 | CONFIG_PTP_1588_CLOCK=y 181 | # CONFIG_HWMON is not set 182 | # CONFIG_X86_PKG_TEMP_THERMAL is not set 183 | CONFIG_MFD_SYSCON=y 184 | CONFIG_DRM=y 185 | CONFIG_DRM_I915=y 186 | CONFIG_FB_VESA=y 187 | CONFIG_BACKLIGHT_LCD_SUPPORT=y 188 | # CONFIG_LCD_CLASS_DEVICE is not set 189 | CONFIG_BACKLIGHT_CLASS_DEVICE=y 190 | # CONFIG_BACKLIGHT_GENERIC is not set 191 | CONFIG_FRAMEBUFFER_CONSOLE=y 192 | CONFIG_USB=y 193 | CONFIG_USB_XHCI_HCD=m 194 | CONFIG_USB_XHCI_PLATFORM=m 195 | CONFIG_USB_EHCI_HCD=m 196 | CONFIG_USB_EHCI_HCD_PLATFORM=m 197 | CONFIG_USB_STORAGE=m 198 | CONFIG_RTC_CLASS=y 199 | # CONFIG_X86_PLATFORM_DEVICES is not set 200 | CONFIG_INTEL_IOMMU=y 201 | CONFIG_INTEL_IOMMU_SVM=y 202 | CONFIG_GENERIC_PHY=y 203 | # CONFIG_BLK_DEV_PMEM is not set 204 | # CONFIG_ND_BLK is not set 205 | # CONFIG_BTT is not set 206 | # CONFIG_FIRMWARE_MEMMAP is not set 207 | # CONFIG_DMIID is not set 208 | CONFIG_GOOGLE_FIRMWARE=y 209 | CONFIG_GOOGLE_MEMCONSOLE_X86_LEGACY=y 210 | # CONFIG_EXT2_FS is not set 211 | CONFIG_EXT4_FS=y 212 | CONFIG_EXT4_USE_FOR_EXT2=y 213 | # CONFIG_DNOTIFY is not set 214 | # CONFIG_INOTIFY_USER is not set 215 | CONFIG_ISO9660_FS=y 216 | CONFIG_JOLIET=y 217 | CONFIG_MSDOS_FS=y 218 | CONFIG_VFAT_FS=y 219 | # CONFIG_PROC_SYSCTL is not set 220 | # CONFIG_PROC_PAGE_MONITOR is not set 221 | CONFIG_TMPFS=y 222 | # CONFIG_MISC_FILESYSTEMS is not set 223 | CONFIG_NLS_DEFAULT="utf8" 224 | CONFIG_NLS_CODEPAGE_437=y 225 | CONFIG_NLS_ISO8859_1=y 226 | CONFIG_NLS_UTF8=y 227 | CONFIG_PRINTK_TIME=y 228 | CONFIG_BOOT_PRINTK_DELAY=y 229 | # CONFIG_ENABLE_WARN_DEPRECATED is not set 230 | # CONFIG_ENABLE_MUST_CHECK is not set 231 | CONFIG_FRAME_WARN=1024 232 | # CONFIG_UNUSED_SYMBOLS is not set 233 | CONFIG_MAGIC_SYSRQ=y 234 | CONFIG_HARDLOCKUP_DETECTOR=y 235 | CONFIG_WQ_WATCHDOG=y 236 | # CONFIG_SCHED_DEBUG is not set 237 | CONFIG_STACKTRACE=y 238 | # CONFIG_DEBUG_BUGVERBOSE is not set 239 | # CONFIG_RCU_TRACE is not set 240 | # CONFIG_FTRACE is not set 241 | # CONFIG_STRICT_DEVMEM is not set 242 | # CONFIG_X86_VERBOSE_BOOTUP is not set 243 | # CONFIG_DOUBLEFAULT is not set 244 | CONFIG_IO_DELAY_0XED=y 245 | CONFIG_OPTIMIZE_INLINING=y 246 | # CONFIG_X86_DEBUG_FPU is not set 247 | CONFIG_HARDENED_USERCOPY=y 248 | CONFIG_CRYPTO_RSA=m 249 | CONFIG_CRYPTO_USER=y 250 | CONFIG_CRYPTO_MCRYPTD=m 251 | CONFIG_CRYPTO_AUTHENC=m 252 | CONFIG_CRYPTO_CCM=m 253 | CONFIG_CRYPTO_GCM=m 254 | CONFIG_CRYPTO_CHACHA20POLY1305=m 255 | CONFIG_CRYPTO_CTS=m 256 | CONFIG_CRYPTO_LRW=y 257 | CONFIG_CRYPTO_PCBC=m 258 | CONFIG_CRYPTO_XTS=y 259 | CONFIG_CRYPTO_KEYWRAP=m 260 | CONFIG_CRYPTO_CMAC=m 261 | CONFIG_CRYPTO_HMAC=y 262 | CONFIG_CRYPTO_XCBC=m 263 | CONFIG_CRYPTO_VMAC=m 264 | CONFIG_CRYPTO_CRC32C_INTEL=y 265 | CONFIG_CRYPTO_CRC32=m 266 | CONFIG_CRYPTO_CRC32_PCLMUL=m 267 | CONFIG_CRYPTO_CRCT10DIF_PCLMUL=m 268 | CONFIG_CRYPTO_POLY1305_X86_64=m 269 | CONFIG_CRYPTO_MD4=m 270 | CONFIG_CRYPTO_MICHAEL_MIC=m 271 | CONFIG_CRYPTO_RMD128=m 272 | CONFIG_CRYPTO_RMD160=m 273 | CONFIG_CRYPTO_RMD256=m 274 | CONFIG_CRYPTO_RMD320=m 275 | CONFIG_CRYPTO_SHA1_SSSE3=y 276 | CONFIG_CRYPTO_SHA256=y 277 | CONFIG_CRYPTO_TGR192=m 278 | CONFIG_CRYPTO_WP512=m 279 | CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m 280 | CONFIG_CRYPTO_AES_NI_INTEL=y 281 | CONFIG_CRYPTO_ANUBIS=m 282 | CONFIG_CRYPTO_ARC4=m 283 | CONFIG_CRYPTO_BLOWFISH=m 284 | CONFIG_CRYPTO_BLOWFISH_X86_64=m 285 | CONFIG_CRYPTO_CAMELLIA=m 286 | CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=m 287 | CONFIG_CRYPTO_CAST5_AVX_X86_64=m 288 | CONFIG_CRYPTO_CAST6_AVX_X86_64=m 289 | CONFIG_CRYPTO_DES3_EDE_X86_64=m 290 | CONFIG_CRYPTO_FCRYPT=m 291 | CONFIG_CRYPTO_KHAZAD=m 292 | CONFIG_CRYPTO_SALSA20=m 293 | CONFIG_CRYPTO_CHACHA20_X86_64=m 294 | CONFIG_CRYPTO_SEED=m 295 | CONFIG_CRYPTO_SERPENT_SSE2_X86_64=m 296 | CONFIG_CRYPTO_SERPENT_AVX2_X86_64=m 297 | CONFIG_CRYPTO_TEA=m 298 | CONFIG_CRYPTO_TWOFISH=m 299 | CONFIG_CRYPTO_TWOFISH_AVX_X86_64=m 300 | CONFIG_CRYPTO_DEFLATE=m 301 | CONFIG_CRYPTO_LZO=y 302 | CONFIG_CRYPTO_842=m 303 | CONFIG_CRYPTO_LZ4=m 304 | CONFIG_CRYPTO_LZ4HC=m 305 | CONFIG_CRYPTO_ANSI_CPRNG=m 306 | CONFIG_CRYPTO_DRBG_HASH=y 307 | CONFIG_CRYPTO_DRBG_CTR=y 308 | CONFIG_CRYPTO_USER_API_HASH=y 309 | CONFIG_CRYPTO_USER_API_SKCIPHER=y 310 | CONFIG_CRYPTO_USER_API_RNG=y 311 | CONFIG_CRYPTO_USER_API_AEAD=y 312 | # CONFIG_CRYPTO_HW is not set 313 | # CONFIG_VIRTUALIZATION is not set 314 | CONFIG_CRC_CCITT=m 315 | CONFIG_CRC_T10DIF=y 316 | CONFIG_CRC_ITU_T=m 317 | CONFIG_CRC7=m 318 | CONFIG_LIBCRC32C=m 319 | CONFIG_CRC8=m 320 | CONFIG_XZ_DEC_TEST=m 321 | CONFIG_CORDIC=m 322 | CONFIG_IRQ_POLL=y 323 | -------------------------------------------------------------------------------- /cpiofile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Creates an in-memory, reproducible cpio file 3 | # Populate an initrd directory with programs and their libraries 4 | # https://www.kernel.org/doc/Documentation/early-userspace/buffer-format.txt 5 | import os 6 | import re 7 | import subprocess 8 | import sys 9 | import hashlib 10 | from tempfile import NamedTemporaryFile 11 | from enum import IntEnum 12 | 13 | 14 | def align(data, b): 15 | if len(data) % b != 0: 16 | data += bytes(b - len(data) % b) 17 | return data 18 | 19 | def cpio_hex(x): 20 | return ("%08x" % (x)).encode('utf-8') 21 | 22 | 23 | # mode includes 24 | class MODE(IntEnum): 25 | S_ISUID = 0o4000 # Set uid 26 | S_ISGID = 0o2000 # Set gid 27 | S_ISVTX = 0o1000 # Save text (sticky bit) 28 | S_ISDIR = 0o40000 # Directory 29 | S_ISFIFO = 0o10000 # FIFO 30 | S_ISREG = 0o100000 # Regular file 31 | S_ISLNK = 0o120000 # Symbolic link 32 | S_ISBLK = 0o60000 # Block special file 33 | S_ISCHR = 0o20000 # Character special file 34 | S_ISSOCK = 0o140000 # Socket 35 | 36 | class CPIOFile: 37 | def __init__(self, filename, data, uid=0, gid=0, major=None, minor=None, mode=0o777): 38 | # remove any duplicate / and strip the leading / 39 | self.filename = filename 40 | self.filename = re.sub(r'//*/', '/', self.filename) 41 | self.filename = re.sub(r'^/*', '', self.filename) 42 | 43 | self.data = data 44 | self.uid = uid 45 | self.gid = gid 46 | 47 | # if major/minor are not set, then this is a regular file 48 | if mode & (MODE.S_ISDIR | MODE.S_ISBLK | MODE.S_ISCHR) == 0: 49 | mode |= MODE.S_ISREG 50 | self.mode = mode 51 | 52 | self.major = major 53 | self.minor = minor 54 | 55 | if self.major is None: 56 | self.major = 0 57 | self.minor = 0 58 | 59 | # returns a blob formatted as a newc cpio entry 60 | # Field name Field size Meaning 61 | # c_magic 6 bytes The string "070701" or "070702" 62 | # c_ino 8 bytes File inode number (always 0) 63 | # c_mode 8 bytes File mode and permissions 64 | # c_uid 8 bytes File uid 65 | # c_gid 8 bytes File gid 66 | # c_nlink 8 bytes Number of links (always 0) 67 | # c_mtime 8 bytes Modification time (always 0) 68 | # c_filesize 8 bytes Size of data field 69 | # c_maj 8 bytes Major part of file device number (always 0) 70 | # c_min 8 bytes Minor part of file device number (always 0) 71 | # c_rmaj 8 bytes Major part of device node reference 72 | # c_rmin 8 bytes Minor part of device node reference 73 | # c_namesize 8 bytes Length of filename, including final \0 74 | # c_chksum 8 bytes Checksum of data field if c_magic is 070702; 75 | # otherwise zero 76 | # followed by namesize bytes of name (padded to be a multiple of 4) 77 | # followed dby filesize bytes of file (padded to be a multiple of 4) 78 | # 79 | def tobytes(self): 80 | name = self.filename.encode('utf-8') + b'\0' 81 | 82 | name_len = len(name) # including nul terminator 83 | data_len = len(self.data) # as is 84 | 85 | # pad filename so that it ends up aligned on a 86 | # four byte block. HOWEVER, it starts offset by 2, 87 | # so there is some weirdness here. note that the 88 | # data is *NOT* padded here, since it will be 89 | # aligned during the final write out 90 | if (name_len+2) % 4 != 0: 91 | name += bytes(4 - ((name_len+2) % 4)) 92 | 93 | return bytearray() \ 94 | + b'070701' \ 95 | + b'00000000' \ 96 | + cpio_hex(self.mode) \ 97 | + cpio_hex(self.uid) \ 98 | + cpio_hex(self.gid) \ 99 | + b'00000000' \ 100 | + b'00000000' \ 101 | + cpio_hex(data_len) \ 102 | + b'00000000' \ 103 | + b'00000000' \ 104 | + cpio_hex(self.major) \ 105 | + cpio_hex(self.minor) \ 106 | + cpio_hex(name_len) \ 107 | + b'00000000' \ 108 | + name \ 109 | + self.data 110 | 111 | class CPIO: 112 | def __init__(self): 113 | self.files = {} 114 | self.verbose = 0 115 | 116 | def normalize(self, filename): 117 | isdir = filename[-1] == '/' 118 | 119 | filename = os.path.normpath(filename) 120 | if filename[0] == '/': 121 | filename = filename[1:] 122 | 123 | return (filename, isdir) 124 | 125 | 126 | def mkdir(self, dirname, mode = 0o777): 127 | if dirname == '': 128 | return 129 | (dirname, isdir) = self.normalize(dirname) 130 | 131 | path = '' 132 | for subdir in re.split(r'/+', dirname): 133 | if path == '': 134 | path = subdir 135 | else: 136 | path += '/' + subdir 137 | if path in self.files: 138 | continue 139 | if path == '': 140 | continue 141 | 142 | self.files[path] = CPIOFile(path, b'', mode = mode | MODE.S_ISDIR) 143 | 144 | def isdir(self, path): 145 | (path,isdir) = self.normalize(path) 146 | 147 | if not path in self.files: 148 | return False 149 | return (self.files[path].mode & MODE.S_ISDIR) != 0 150 | 151 | def add(self,filename,src_filename=None, data=None,mode=0o655): 152 | (filename,isdir) = self.normalize(filename) 153 | 154 | if isdir or self.isdir(filename): 155 | # destination directory 156 | fname = os.path.split(src_filename)[1] 157 | filename = os.path.join(filename, fname) 158 | 159 | if filename in self.files: 160 | #print("%s -> %s: destination already exists!" % (src_filename,filename), file=sys.stderr) 161 | return 162 | 163 | # read in the data from the file if not provided 164 | if data is None: 165 | mode = os.stat(src_filename).st_mode 166 | with open(src_filename, "rb") as datafile: 167 | data = datafile.read() 168 | 169 | # if the dest path does not already exist, be sure to make it 170 | self.mkdir(os.path.split(filename)[0]) 171 | 172 | if self.verbose: 173 | data_hash = '---' #hashlib.sha256(data).hexdigest() 174 | print("add %s -> %s (%d bytes) %s" % (src_filename, filename, len(data), data_hash)) 175 | # if depsfile: 176 | # print("\t" + src + " \\", file=depsfile) 177 | 178 | self.files[filename] = CPIOFile(filename, data, mode=mode) 179 | 180 | def mknod(self, filename, devtype, major, minor): 181 | (filename,isdir) = self.normalize(filename) 182 | mode = 0o666 183 | if devtype == 'b': 184 | mode |= MODE.S_ISBLK 185 | elif devtype == 'c': 186 | mode |= MODE.S_ISCHR 187 | else: 188 | throw("bad dev type") 189 | 190 | # if the dest path does not already exist, be sure to make it 191 | self.mkdir(os.path.split(filename)[0]) 192 | 193 | major = int(major) 194 | minor = int(minor) 195 | 196 | if self.verbose: 197 | print("mknod %s %s %d %d" % (filename, devtype, major, minor)) 198 | 199 | self.files[filename] = CPIOFile( 200 | filename, 201 | b'', 202 | mode = mode, 203 | major = major, 204 | minor = minor) 205 | 206 | def symlink(self, filename, dest): 207 | (filename,isdir) = self.normalize(filename) 208 | 209 | if self.verbose: 210 | print("symlink %s -> %s" % (filename, dest)) 211 | 212 | self.mkdir(os.path.split(filename)[0]) 213 | self.files[filename] = CPIOFile( 214 | filename, 215 | dest.encode('utf-8'), 216 | mode = 0o777 | MODE.S_ISLNK) 217 | 218 | def tobytes(self, compressed=False): 219 | image = bytearray() 220 | for dst in sorted(self.files): 221 | #print(dst) 222 | f = self.files[dst] 223 | 224 | # align before starting the next file 225 | image = align(image, 4) 226 | 227 | image += f.tobytes() 228 | 229 | # align before starting the trailer file 230 | image = align(image, 4) 231 | image += CPIOFile("TRAILER!!!", b'', mode=0).tobytes() 232 | if self.verbose: 233 | print("**** CPIOFile done") 234 | 235 | if compressed: 236 | # write to a temp file first 237 | old_len = len(image) 238 | 239 | print("**** Starting compression") 240 | with NamedTemporaryFile() as tmp: 241 | tmp.write(image) 242 | tmp.flush() 243 | sub = subprocess.run([ 244 | "xz", 245 | "--check=crc32", 246 | "--lzma2=dict=256KiB", 247 | "--threads=0", 248 | "--stdout", 249 | tmp.name 250 | ], capture_output=True) 251 | if sub.returncode != 0: 252 | #print(sub.stderr, file=sys.stderr) 253 | return None 254 | image = sub.stdout 255 | 256 | print("**** Aligning image") 257 | # pad compressed data to a full block size to make linux 258 | # happy if this is ever concatenated with another initrd 259 | image = align(image, 512) 260 | return image 261 | 262 | -------------------------------------------------------------------------------- /heads-builder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Build the Heads runtime (coreboot, initrd, kernel) with worldbuilder 3 | # Currently produces x230 and qemu to demonstrate multiple build targets 4 | # 5 | import worldbuilder 6 | import cpiofile 7 | import os 8 | import sys 9 | import traceback 10 | import glob 11 | 12 | from worldbuilder.util import extend, zero_hash, sha256hex, exists, mkdir, writefile 13 | from worldbuilder.submodule import global_mods 14 | from worldbuilder import commands 15 | 16 | from worldbuilder.crosscompile import gcc, crossgcc, cross_tools_nocc, cross_tools32_nocc, cross_tools, cross, target_arch, target_arch, musl, cross_gcc 17 | from worldbuilder import crosscompile 18 | 19 | from worldbuilder.linux import LinuxSrc, Linux 20 | from worldbuilder.coreboot import CorebootSrc, Coreboot 21 | 22 | # cache server can be passed in the environment 23 | worldbuilder.submodule.cache_server = os.getenv("CACHE_SERVER", None) 24 | 25 | for modname in sorted(glob.glob("modules/*")): 26 | try: 27 | with open(modname, "r") as f: 28 | exec(f.read()) 29 | except Exception as e: 30 | print(modname + ": failed to parse", file=sys.stderr) 31 | print(traceback.format_exc(), file=sys.stderr) 32 | exit(1) 33 | 34 | def Heads( 35 | board, 36 | kernel, 37 | kernel_version, 38 | coreboot_version, 39 | tools, 40 | extra_files = None, 41 | cmdline = None, 42 | ): 43 | initrdfile = worldbuilder.Initrd(board, 44 | filename = "initrd.cpio.xz", 45 | depends = tools, 46 | dirs = [ "/bin", "/lib" ], 47 | files = extra_files, 48 | symlinks = [ 49 | [ "/bin/sh", "busybox" ], 50 | [ "/lib/ld-musl-x86_64.so.1", "libc.so" ], 51 | [ "/lib64", "lib" ], 52 | ], 53 | devices = [ 54 | [ "/dev/console", "c", 5, 1 ], 55 | ], 56 | ) 57 | 58 | linux_src = LinuxSrc( 59 | version = kernel_version, 60 | patches = [ "patches/linux-%(version)s/*" ], 61 | ) 62 | 63 | linux = Linux( 64 | name = kernel, 65 | linux_src = linux_src, 66 | config = "config/linux-" + kernel + ".config", 67 | cmdline = cmdline or "console=ttyS0", 68 | compiler = worldbuilder.crosscompile, 69 | ) 70 | 71 | coreboot_src = CorebootSrc( 72 | version = coreboot_version, 73 | patches = [ "patches/coreboot-%(version)s/*" ], 74 | ) 75 | 76 | coreboot = Coreboot( 77 | name = board, 78 | src = coreboot_src, 79 | config = "config/coreboot-" + board + ".config", 80 | kernel = linux, 81 | initrd = initrdfile, 82 | compiler = worldbuilder.crosscompile, 83 | ) 84 | 85 | return coreboot 86 | 87 | qemu_firmware = Heads( 88 | board = "qemu", 89 | kernel = "virtio", 90 | kernel_version = "5.4.117", 91 | coreboot_version = "4.15", 92 | tools = [ 93 | "fbwhiptail", 94 | "dropbear", 95 | "cryptsetup2", 96 | "lvm2", 97 | "flashrom", 98 | "pciutils", 99 | "busybox", 100 | "kexec", 101 | "openssh", 102 | ], 103 | ) 104 | 105 | x230_firmware = Heads( 106 | board = "x230", 107 | kernel = "x230", 108 | kernel_version = "4.14.62", 109 | coreboot_version = "4.13", 110 | tools = [ 111 | "fbwhiptail", 112 | "dropbear", 113 | "cryptsetup2", 114 | "lvm2", 115 | "flashrom", 116 | "pciutils", 117 | "busybox", 118 | "kexec", 119 | ], 120 | ) 121 | 122 | builder = worldbuilder.Builder([ qemu_firmware, x230_firmware ]) 123 | 124 | if os.getenv("SINGLE_THREAD", None): 125 | builder.single_thread = True 126 | 127 | if len(sys.argv) > 1: 128 | if sys.argv[1] == "cache": 129 | exit(builder.cache_create("build/cache")) 130 | elif sys.argv[1] == "check": 131 | exit(builder.check()) 132 | builder.mods = sys.argv[1:] 133 | 134 | if not builder.build_all(): 135 | exit(-1) 136 | -------------------------------------------------------------------------------- /helloworld.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.9 2 | # build a small initd world 3 | import worldbuilder 4 | import cpiofile 5 | import os 6 | 7 | from crosscompile import gcc, crossgcc, cross_tools_nocc, cross_tools, cross, target_arch, musl 8 | 9 | linux = worldbuilder.Submodule("linux", 10 | depends = [ crossgcc ], # doesn't need musl so it can start earlier 11 | url = "https://cdn.kernel.org/pub/linux/kernel/v%(major)s.x/linux-%(version)s.tar.xz", 12 | version = "5.4.117", 13 | tarhash = "4e989b5775830092e5c76b5cca65ebff862ad0c87d0b58c3a20d415c3d4ec770", 14 | config_files = [ "config/linux-virtio.config" ], 15 | configure = [ 16 | "make", 17 | "-C%(src_dir)s", 18 | "O=%(rout_dir)s", 19 | "olddefconfig", 20 | *cross_tools_nocc, 21 | #"CC=" + cross + "gcc", 22 | ], 23 | #depends = [ binutils ], # should it use the cross compiler? 24 | make = [ 25 | worldbuilder.kbuild_make, 26 | [ "make", "headers_install" ], 27 | ] 28 | ) 29 | 30 | linux_hdrs = "-I%(linux.out_dir)s/usr/include" 31 | 32 | busybox = worldbuilder.Submodule("busybox", 33 | depends = [ gcc, linux ], 34 | url = "https://busybox.net/downloads/busybox-%(version)s.tar.bz2", 35 | version = "1.32.0", 36 | tarhash = "c35d87f1d04b2b153d33c275c2632e40d388a88f19a9e71727e0bbbff51fe689", 37 | config_files = [ "config/busybox.config" ], 38 | #patches = [ "patches/busybox-1.28.0.patch" ], 39 | configure = [ 40 | "make", 41 | "-C%(src_dir)s", 42 | "O=%(rout_dir)s", 43 | "oldconfig", 44 | *cross_tools, 45 | "CFLAGS=" + linux_hdrs, 46 | ], 47 | make = [ 48 | *worldbuilder.kbuild_make, 49 | "V=1", 50 | "install", 51 | *cross_tools, 52 | "CFLAGS=" + linux_hdrs, 53 | ], 54 | ) 55 | 56 | util_linux = worldbuilder.Submodule("util-linux", 57 | version = "2.29.2", 58 | url = "https://www.kernel.org/pub/linux/utils/util-linux/v%(major)s.%(minor)s/util-linux-%(version)s.tar.xz", 59 | tarhash = "accea4d678209f97f634f40a93b7e9fcad5915d1f4749f6c47bee6bf110fe8e3", 60 | depends = [ linux, gcc ], 61 | configure = [ 62 | worldbuilder.configure_cmd, 63 | "--prefix=%(install_dir)s", 64 | "--target", target_arch, 65 | "--host", 'x86_64-linux-gnu', 66 | "--without-ncurses", 67 | "--without-ncursesw", 68 | "--without-tinfo", 69 | "--without-udev", 70 | "--without-python", 71 | "--disable-bash-completion", 72 | "--disable-all-programs", 73 | "--enable-libuuid", 74 | "--enable-libblkid", 75 | *cross_tools, 76 | "CFLAGS=" + linux_hdrs, 77 | ], 78 | make = [ "make", "install", "V=1" ], 79 | ) 80 | 81 | zlib = worldbuilder.Submodule('zlib', 82 | depends = [ gcc ], 83 | version = '1.2.11', 84 | url = 'https://www.zlib.net/zlib-%(version)s.tar.gz', 85 | tarhash = 'c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1', 86 | configure = [ 87 | worldbuilder.configure_cmd, 88 | "--prefix=%(install_dir)s", 89 | *cross_tools, 90 | ], 91 | make = [ "make" ], 92 | ) 93 | #zlib_libraries := libz.so.1 94 | 95 | kexec = worldbuilder.Submodule('kexec', 96 | version = '2.0.20', 97 | url = 'https://kernel.org/pub/linux/utils/kernel/kexec/kexec-tools-%(version)s.tar.gz', 98 | tarhash = 'cb16d79818e0c9de3bb3e33ede5677c34a1d28c646379c7ab44e0faa3eb57a16', 99 | patches = [ 100 | "patches/kexec-2.0.20.patch", 101 | "patches/kexec-2.0.20-duplicate-symbols.patch", 102 | ], 103 | depends = [ linux, gcc ], 104 | configure = [ 105 | worldbuilder.configure_cmd, 106 | "--prefix=%(install_dir)s", 107 | "--host", 'x86_64-linux-gnu', #'i386-elf-linux', 108 | "--target", 'x86_64', 109 | "--without-lzma", 110 | *cross_tools, 111 | "CFLAGS=" + linux_hdrs, 112 | ], 113 | make = [ "make", "install" ], 114 | bin_dir = 'sbin', 115 | ) 116 | 117 | pciutils = worldbuilder.Submodule("pciutils", 118 | depends = [ gcc, linux ], 119 | version = "3.5.4", 120 | url = "https://www.kernel.org/pub/software/utils/%(name)s/%(name)s-%(version)s.tar.xz", 121 | tarhash = "64293c6ab9318c40ef262b76d87bd9097531759752bac556e50979b1e63cfe66", 122 | patches = [ "patches/pciutils-3.5.4.patch" ], 123 | 124 | # the makefile writes in the source directory 125 | dirty = True, 126 | 127 | configure = [ "true" ], 128 | 129 | # IDSDIR must be set to a constant during the build, 130 | # but not during the install to make the libpci.so.3 131 | # reproducible. Otherwise the build path will be embedded 132 | # in the library and executables. 133 | make = [ [ 134 | "make", 135 | "ZLIB=no", 136 | "HWDB=no", 137 | "LIBKMOD=no", 138 | "SHARED=yes", 139 | "IDSDIR=/", 140 | "PREFIX=/", 141 | *cross_tools, 142 | "CFLAGS=-fpic " + linux_hdrs, 143 | ], [ 144 | "make", 145 | #"ZLIB=no", 146 | #"HWDB=no", 147 | #"LIBKMOD=no", 148 | #"SHARED=yes", 149 | "PREFIX=/", 150 | "DESTDIR=%(install_dir)s", 151 | "install", 152 | "install-lib", 153 | ] ], 154 | bin_dir = "sbin", 155 | ) 156 | 157 | #pciutils_output := lspci 158 | #pciutils_libraries := lib/libpci.so.3.5.4 ../../install/lib/libpci.so.3 159 | 160 | 161 | #kexec_output := build/sbin/kexec 162 | 163 | #build = worldbuilder.Builder([kexec, util_linux, linux, busybox]) 164 | #build = builder.Builder([busybox, kexec, util_linux]) 165 | build = worldbuilder.Builder([pciutils, busybox, kexec, util_linux]) 166 | #build.check() 167 | if not build.build_all(): 168 | exit(-1) 169 | 170 | # make a ramdisk 171 | cpio = cpiofile.CPIO() 172 | 173 | cpio.mkdir("/lib64") 174 | cpio.mkdir("/lib") 175 | #cpio.symlink("/lib/x86_64-linux-gnu", "../lib64") 176 | 177 | cpio.mknod("/dev/console", "c", 5, 1) 178 | 179 | cpio.mkdir("/bin") 180 | cpio.add("/bin", os.path.join(kexec.bin_dir, "kexec")) 181 | 182 | cpio.add("/bin", os.path.join(pciutils.bin_dir, "lspci")) 183 | 184 | cpio.add("/bin", os.path.join(busybox.bin_dir, "busybox")) 185 | cpio.symlink("/bin/sh", "./busybox") 186 | 187 | cpio.add("/lib", os.path.join(musl.lib_dir, "libc.so")) 188 | cpio.symlink("/lib/ld-musl-x86_64.so.1", "libc.so") 189 | 190 | image = cpio.tobytes() 191 | with open("image.cpio", "wb") as f: 192 | f.write(image) 193 | -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tinyinit - finish kernel setup and get out of the way. 3 | * 4 | * Setup a few directories, mount a few filesystems, 5 | * and then exec the real application. 6 | * 7 | * By writing this as a small C program it avoids the need 8 | * to bring in bash and most of coreutils for smaller 9 | * unikernel images. 10 | */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | // status updates 23 | #include 24 | #include 25 | 26 | static int forkit(const char * filename) 27 | { 28 | int fd = open(filename, O_RDONLY); 29 | if (fd < 0) 30 | { 31 | fprintf(stderr, "%s not found; not sure what to do!\n", filename); 32 | return -1; 33 | } 34 | 35 | char args[4096]; 36 | ssize_t len = read(fd, args, sizeof(args)); 37 | //fprintf(stderr, "init: read %zu bytes\n", len); 38 | if (len < 0) 39 | { 40 | perror(filename); 41 | return -1; 42 | } 43 | 44 | close(fd); 45 | 46 | char *argv[64] = {}; 47 | int argc = 0; 48 | 49 | argv[argc++] = args; 50 | 51 | fprintf(stderr, "%s: execv('%s'", filename, argv[0]); 52 | 53 | // stop before the end of the argument data 54 | for(int offset = 0 ; offset < len-1 ; offset++) 55 | { 56 | if (args[offset] != '\0') 57 | continue; 58 | 59 | char * arg = &args[offset+1]; 60 | argv[argc++] = arg; 61 | 62 | fprintf(stderr, ",'%s'", arg); 63 | } 64 | 65 | // terminate the list 66 | argv[argc] = NULL; 67 | fprintf(stderr, ")\n"); 68 | 69 | // invoke it and hope for the best! 70 | int pid = vfork(); 71 | if (pid == 0) 72 | { 73 | execv(argv[0], argv); 74 | exit(-1); 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | 81 | // occasionally log some data 82 | static void loginfo(void) 83 | { 84 | while(1) 85 | { 86 | // schedule another wakeup 87 | sleep(60); 88 | 89 | struct sysinfo info; 90 | if (sysinfo(&info) < 0) 91 | { 92 | perror("sysinfo"); 93 | continue; 94 | } 95 | 96 | const float load_scale = 1.0f / (1 << SI_LOAD_SHIFT); 97 | const unsigned long mem_used = info.totalram - info.freeram; 98 | const int mem_percent = (100 * mem_used) / info.totalram; 99 | 100 | syslog(mem_percent > 80 ? LOG_ALERT : LOG_DEBUG, 101 | "load %.2f,%.2f,%.2f ram %ld/%ld (%d%%) procs %d", 102 | info.loads[0] * load_scale, 103 | info.loads[1] * load_scale, 104 | info.loads[2] * load_scale, 105 | mem_used, 106 | info.totalram, 107 | mem_percent, 108 | info.procs 109 | ); 110 | 111 | } 112 | } 113 | 114 | int main(void) 115 | { 116 | // these should already exist, but just in case 117 | fprintf(stderr, "init: creating directories\n"); 118 | mkdir("/root", 0755); 119 | mkdir("/proc", 0755); 120 | mkdir("/sys", 0755); 121 | mkdir("/tmp", 0755); 122 | mkdir("/dev", 0755); 123 | mkdir("/run", 0755); 124 | mkdir("/var", 0755); 125 | 126 | fprintf(stderr, "init: mounting filesystems\n"); 127 | mount("none", "/proc", "proc", 0, ""); 128 | mount("none", "/dev", "devtmpfs", 0, ""); 129 | mount("none", "/sys", "sysfs", 0, ""); 130 | mount("none", "/sys/kernel/security", "securityfs", 0, ""); 131 | mount("none", "/tmp", "tmpfs", 0, ""); 132 | 133 | // this breaks things in /var, and we can't mount a separate /var 134 | // since they might have pre-created directories in it. 135 | //fprintf(stderr, "init: remounting root read only\n"); 136 | //mount("none", "/", "rootfs", MS_REMOUNT | MS_RDONLY, ""); 137 | 138 | int fd = open("/dev/console", O_RDWR); 139 | if (fd >= 0) 140 | { 141 | dup2(fd, 0); 142 | dup2(fd, 1); 143 | dup2(fd, 2); 144 | } 145 | 146 | // if it wasn't one of the stdio fd's, close it now 147 | if (fd > 2) 148 | close(fd); 149 | 150 | // set a shell prompt, just in case 151 | setenv("PS1", "\\w# ", 1); 152 | 153 | glob_t globbuf; 154 | int rc = glob("/init.d/*", 0, NULL, &globbuf); 155 | const int matches = globbuf.gl_pathc; 156 | if (rc != 0 || matches == 0) 157 | { 158 | fprintf(stderr, "init: no programs to run? we're done here\n"); 159 | return -1; 160 | } 161 | 162 | fprintf(stderr, "init: %d startup items found\n", matches); 163 | for(int i = 0 ; i < matches ; i++) 164 | { 165 | if (forkit(globbuf.gl_pathv[i]) == 0) 166 | continue; 167 | fprintf(stderr, "init: failed! we're done here\n"); 168 | return -1; 169 | } 170 | 171 | globfree(&globbuf); 172 | 173 | // we do not need stdin, but our children might 174 | close(0); 175 | 176 | openlog("init", 0, LOG_DAEMON); 177 | 178 | if (fork() == 0) 179 | loginfo(); 180 | 181 | while(1) 182 | { 183 | 184 | int status; 185 | pid_t pid = wait(&status); 186 | if (status != 0) 187 | syslog(LOG_WARNING, "pid %d exited status %08x", pid, status); 188 | else 189 | fprintf(stderr, "init: pid %d exited status %08x\n", (int) pid, status); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /initrd-builder: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Populate an initrd directory with programs and their libraries 3 | # https://www.kernel.org/doc/Documentation/early-userspace/buffer-format.txt 4 | import sys 5 | import re 6 | import os 7 | import cpiofile 8 | import traceback 9 | import argparse 10 | import subprocess 11 | from tempfile import NamedTemporaryFile 12 | 13 | bindir = "bin" 14 | libdir = "lib64" 15 | verbose = False 16 | cwd = '.' 17 | no_strip = False 18 | 19 | depsfile = None 20 | deps = {} 21 | cpio = cpiofile.CPIO() 22 | 23 | def system(*s): 24 | # do not close file descriptors, which will allow 25 | # communication from sub-make invocations to the make 26 | # that invoked us. allow failures 27 | return subprocess.run(s, close_fds=False, capture_output=True) 28 | 29 | def die(s): 30 | print(s, file=sys.stderr) 31 | exit(1) 32 | 33 | def filemode(filename): 34 | try: 35 | s = os.stat(filename) 36 | return s.st_mode 37 | except Exception as e: 38 | print(e, file=sys.stderr) 39 | return None 40 | def exists(f): 41 | try: 42 | os.stat(f) 43 | return True 44 | except Exception as e: 45 | return False 46 | def readfile(filename): 47 | with open(filename, "rb") as f: 48 | return f.read() 49 | 50 | def deps_add(filename): 51 | #print(f"{filename=} {filename in deps}") 52 | if filename in deps: 53 | return False 54 | deps[filename] = 1 55 | if depsfile: 56 | print("\t" + filename + " \\", file=depsfile) 57 | return True 58 | 59 | ### try stripping executables and libraries before loading them 60 | def try_strip(filename): 61 | data = readfile(filename) 62 | if no_strip or data[0:4] != b'\x7fELF': 63 | return data 64 | 65 | try: 66 | with NamedTemporaryFile() as tmp: 67 | rc = system("strip", "-o", tmp.name, filename) 68 | if rc.returncode == 0: 69 | # strip succeeded, use it instead 70 | new_data = readfile(tmp.name) 71 | #print(f"{filename}: {len(data)} -> {len(new_data)}") 72 | return new_data 73 | except Exception as e: 74 | # something went wrong with strip, use the file as is 75 | pass 76 | 77 | return data 78 | 79 | def process_line(line): 80 | words = re.split(r'\s+', line) 81 | if words[0] == "symlink": 82 | # the filename is the second part, the data in that 83 | # file is the path to the real file 84 | cpio.symlink(words[2], words[1]) 85 | return 86 | if words[0] == "mkdir": 87 | mode = 0o777 88 | if len(words) > 2: 89 | mode = int(words[2], 8) 90 | cpio.mkdir(words[1], mode) 91 | return 92 | if words[0] == "mknod": 93 | # mknod path [c|b] major minor 94 | cpio.mknod(words[1], words[2], words[3], words[4]) 95 | return 96 | if words[0] == "exec": 97 | # command line stuff to be read by init 98 | # exec /init.d/10-module cmd [args...] 99 | cpio.add(words[1], data=words[2:]) 100 | return 101 | 102 | # normal file 103 | filename = words[0] 104 | dest = bindir 105 | if len(words) > 1: 106 | dest = words[1] 107 | 108 | # - marks optional files; do not die if they do not exist 109 | # ! marks forced files; do not die if their dependencies do not exist 110 | optional = False 111 | force = False 112 | if filename[0] == '-': 113 | optional = True 114 | filename = filename[1:] 115 | if filename[0] == '!': 116 | force = True 117 | filename = filename[1:] 118 | 119 | # if a relative file name is provided, update it with the cwd 120 | if filename[0] != '/': 121 | filename = os.path.join(cwd, filename) 122 | 123 | if optional and not exists(filename): 124 | print(filename + ": skipping") 125 | return 126 | 127 | size = 0 128 | 129 | if filename.endswith('/'): 130 | # recursive directory copy 131 | olddir = os.path.normpath(filename) 132 | 133 | if len(words) > 2: 134 | pattern = words[2] 135 | else: 136 | # skip editor temp files .*.swp 137 | pattern = r'\.[^.]*\.sw[po]$' 138 | 139 | for root, dirs, files in os.walk(olddir): 140 | # strip the non-relative path part 141 | # is there a better way to do this? 142 | newroot = os.path.join(dest, os.path.relpath(root, start=olddir)) 143 | cpio.mkdir(newroot) 144 | for f in files: 145 | oldname = os.path.join(root, f) 146 | newname = os.path.join(newroot, f) 147 | 148 | # filter any that match the exclusion pattern 149 | if re.search(pattern, oldname): 150 | continue 151 | 152 | data = readfile(oldname) 153 | cpio.add(newname, data=data) 154 | 155 | if deps_add(oldname): 156 | size += len(data) 157 | 158 | if verbose: 159 | print("%s: %d (recursive)" % (olddir, size)) 160 | 161 | 162 | # ldd is *not* done on recursive directories 163 | return 164 | 165 | # strip the local path 166 | dest_filename = os.path.basename(filename) 167 | 168 | data = try_strip(filename) 169 | cpio.add(dest + "/" + dest_filename, data=data, mode=filemode(filename)) 170 | 171 | if deps_add(filename): 172 | size += len(data) 173 | 174 | file_deps = system("ldd", filename) 175 | if file_deps.returncode != 0 \ 176 | or file_deps.stderr == b'\tnot a dynamic executable\n': 177 | if verbose: 178 | print("%s: %d" % (filename, size)) 179 | return 180 | 181 | dep_size = 0 182 | for dep in file_deps.stdout.split(b'\n'): 183 | dep = dep.decode('utf-8') 184 | if re.search(r'not found', dep): 185 | print("MISSING LIBRARY: ", dep, file=sys.stderr) 186 | # do not die on optional missing dependencies 187 | if force: 188 | continue 189 | 190 | dep = re.sub(r'^.* => ', '', dep) 191 | dep = re.sub(r'^\s*', '', dep) 192 | lib = dep.split(' ')[0] 193 | 194 | if lib == '' or re.match(r'^linux-vdso', lib): 195 | continue 196 | 197 | # strip the local path and put the library in the libdir 198 | dest_lib = os.path.basename(lib) 199 | data = try_strip(lib) 200 | cpio.add(libdir + "/" + dest_lib, data=data) 201 | if deps_add(lib): 202 | dep_size += len(data) 203 | 204 | if verbose: 205 | print("%s: %d (deps %d)" % (filename, size, dep_size)) 206 | 207 | parser = argparse.ArgumentParser() 208 | parser.add_argument('files', 209 | nargs='+', 210 | help="Configuration files to parse") 211 | parser.add_argument('-o', '--output', 212 | dest='cpio', type=str, 213 | default='-', 214 | help="Output of the cpio file") 215 | parser.add_argument( '-v', '--verbose', 216 | dest='verbose', action='store_true', 217 | help="Log every file included") 218 | parser.add_argument( '-c', '--xz', 219 | dest='xz', action='store_true', 220 | help="Compress the initrd with xz") 221 | parser.add_argument('-r', '--relative', 222 | dest='relative', action='store_true', 223 | help="Use the path of the config for relative path files") 224 | parser.add_argument('-M', '--deps', 225 | dest='deps', type=str, 226 | help="Output dependencies for Makefile rebuilds") 227 | parser.add_argument('--no-strip', 228 | dest='no_strip', action='store_true', 229 | help="Do not strip libraries and executables") 230 | parser.add_argument('--add', 231 | dest='extra', type=str, action='append', 232 | help="Extra binaries to be included") 233 | 234 | args = parser.parse_args() 235 | verbose = args.verbose 236 | #cpio.verbose = verbose 237 | initrd_filename = args.cpio 238 | no_strip = args.no_strip 239 | 240 | if args.deps: 241 | depsfile = open(args.deps, "w") 242 | print("# Autogenerated dependencies for " + initrd_filename, file=depsfile) 243 | print(initrd_filename + ": \\", file=depsfile) 244 | 245 | 246 | for filename in args.files: 247 | if args.relative: 248 | cwd = os.path.split(filename)[0] 249 | if cwd == '': 250 | cwd = '.' 251 | 252 | with open(filename, "r") as f: 253 | linenum = 0 254 | for line in f.readlines(): 255 | linenum += 1 256 | 257 | # strip any commands and skip blank lines 258 | line = re.sub(r'\n$', '', line) 259 | line = re.sub(r'^\s*', '', line) 260 | line = re.sub(r'\s*#.*$','', line) 261 | if len(line) == 0: 262 | continue 263 | 264 | #print("%s:%d: %s" % (filename, linenum, line)) 265 | 266 | try: 267 | process_line(line) 268 | except Exception as e: 269 | print("%s:%d: failed '%s' (cwd=%s)" % (filename, linenum, line, cwd), e, file=sys.stderr) 270 | print(traceback.format_exc()) 271 | exit(1) 272 | 273 | # restore the cwd to the current directory 274 | cwd = '.' 275 | if args.extra: 276 | for line in args.extra: 277 | try: 278 | process_line(line) 279 | except Exception as e: 280 | print("%s:%d: failed '%s'" % (filename, linenum, line), e, file=sys.stderr) 281 | print(traceback.format_exc()) 282 | exit(1) 283 | 284 | if verbose: 285 | print("**** all files added") 286 | 287 | compressed = args.xz or initrd_filename.endswith('.xz') 288 | image = cpio.tobytes(compressed) 289 | 290 | if verbose: 291 | print("**** writing cpio image ") 292 | 293 | if initrd_filename == '-': 294 | sys.stdout.buffer.write(image) 295 | else: 296 | with open(initrd_filename, "wb") as initrd: 297 | initrd.write(image) 298 | -------------------------------------------------------------------------------- /jump-builder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.9 2 | # Build the jumphost 3 | import worldbuilder 4 | import initrd 5 | import os 6 | import sys 7 | from glob import glob 8 | import traceback 9 | 10 | kernel = "virtio" 11 | board = None 12 | 13 | from worldbuilder import extend, zero_hash, sha256hex, global_mods, exists, mkdir, writefile, global_submodules 14 | 15 | #from crosscompile import gcc, crossgcc, cross_tools_nocc, cross_tools32_nocc, cross_tools, cross, target_arch, musl 16 | from localcompile import gcc, cross_tools_nocc, cross_tools, cross, target_arch 17 | 18 | for modname in glob("modules/*"): 19 | try: 20 | with open(modname, "r") as f: 21 | exec(f.read()) 22 | except Exception as e: 23 | print(modname + ": failed to parse", file=sys.stderr) 24 | print(traceback.format_exc(), file=sys.stderr) 25 | exit(1) 26 | 27 | initrdfile = initrd.Initrd("jump", 28 | depends = [ "openssh" ], 29 | filename = "initrd.cpio", 30 | files = { 31 | "/bin": [ 32 | "%(openssh.out_dir)s/sshd", 33 | #"%(dropbear.bin_dir)s/ssh", 34 | #"%(kexec.bin_dir)s/kexec", 35 | ], 36 | "/lib": [ 37 | #"%(musl.lib_dir)s/libc.so", 38 | ], 39 | "/": [ 40 | "init", 41 | ], 42 | }, 43 | symlinks = [ 44 | [ "/lib/ld-musl-x86_64.so.1", "libc.so" ], 45 | [ "/lib64", "lib" ], 46 | ], 47 | devices = [ 48 | [ "/dev/console", "c", 5, 1 ], 49 | ], 50 | ) 51 | 52 | initrd_filename = "%(initrd-jump)s/initrd.cpio" 53 | 54 | bzimage = global_submodules("linux-" + kernel) 55 | bzimage.depends.append(initrdfile) 56 | bzimage.dep_files.append(initrd_filename) 57 | bzimage.config_append.append('CONFIG_INITRAMFS_SOURCE="' + initrd_filename + '"') 58 | 59 | build = worldbuilder.Builder([bzimage]) 60 | 61 | #build.check() 62 | if not build.build_all(): 63 | exit(-1) 64 | -------------------------------------------------------------------------------- /linux-builder: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Build a Linux kernel based on a config file 3 | # This can also be applied to other KConfig tools and some Makefile tools 4 | import argparse 5 | import os 6 | import sys 7 | import subprocess 8 | import hashlib 9 | import shlex 10 | from tempfile import NamedTemporaryFile 11 | 12 | verbose = 1 13 | 14 | def system(*s, cwd=None): 15 | # do not close file descriptors, which will allow 16 | # communication from sub-make invocations to the make 17 | # that invoked us 18 | if verbose: 19 | print(s) 20 | subprocess.run(s, check=True, close_fds=False, cwd=cwd) 21 | def die(*s): 22 | print(*s, file=sys.stderr) 23 | exit(1) 24 | def info(s): 25 | if verbose > 0: 26 | print(s, file=sys.stderr) 27 | def debug(s): 28 | if verbose > 1: 29 | print(s, file=sys.stderr) 30 | def exists(f): 31 | try: 32 | os.stat(f) 33 | return True 34 | except Exception as e: 35 | return False 36 | def readfile(filename): 37 | with open(filename, "rb") as f: 38 | data = f.read() 39 | data_hash = hashlib.sha256(data).hexdigest() 40 | return (data, data_hash) 41 | def writefile(filename, data): 42 | with open(filename, "wb") as f: 43 | f.write(data) 44 | 45 | # allow $MAKE to be overridden in the environment, which 46 | # will inherit from Makefiles. Note that it is split 47 | # into separate words so that the shell is not invoked 48 | # on sub-make builds 49 | make = os.getenv("MAKE") 50 | if not make: 51 | make = "make" 52 | 53 | parser = argparse.ArgumentParser() 54 | parser.add_argument('-O', '--output-dir', 55 | dest='output_dir', type=str, 56 | default='build', 57 | help="Directory for Linux builds") 58 | parser.add_argument('-S', '--src-dir', 59 | dest='src_dir', type=str, 60 | default='src', 61 | help="Directory for Linux source") 62 | parser.add_argument('-F', '--ftp-dir', 63 | dest='ftp_dir', type=str, 64 | default='ftp', 65 | help="Directory for source archives") 66 | parser.add_argument('-T', '--tag', 67 | dest='tag', type=str, 68 | default=None, 69 | help="Short name for the build (default inferred from config file)") 70 | parser.add_argument('-V', '--version', 71 | dest='version', type=str, 72 | default='5.4.117', 73 | help="Linux kernel version to build") 74 | parser.add_argument( '-v', '--verbose', 75 | dest='verbose', action='count', default=0, 76 | help="Verbose build") 77 | parser.add_argument( '-s', '--silent', 78 | dest='verbose', action='store_const', const=0, 79 | help="Verbose build (add more for more verbosity)") 80 | parser.add_argument( '-m', '--menuconfig', 81 | dest='menuconfig', action='store_true', 82 | help="Run menuconfig on the config file") 83 | parser.add_argument('--clean', 84 | dest='clean', action='store_true', 85 | help="Clean the build directory and source directory") 86 | parser.add_argument('-c', '--config', 87 | dest='config', type=str, 88 | default=None, 89 | required=True, 90 | help="Linux kernel config file (required)") 91 | parser.add_argument('-p', '--patch', 92 | dest='patches', type=str, action='append', 93 | default=None, 94 | help="Linux kernel patch file (optional, can be multiple)") 95 | parser.add_argument('--hash', 96 | dest='hash', type=str, 97 | default=None, 98 | help="sha256 hash of the kernel source file") 99 | parser.add_argument( '-M', '--make', 100 | dest='make', type=str, 101 | default=make, 102 | help="Override the $(MAKE) environment variable") 103 | parser.add_argument( '-j', '--jobs', 104 | dest='make_jobs', type=int, 105 | default=None, 106 | help="Number of parallel make jobs to invoke") 107 | parser.add_argument( '-H', '--hostname', 108 | dest='hostname', type=str, 109 | default=None, 110 | help="Override the default hostname in the linux config") 111 | parser.add_argument( '-C', '--cmdline', 112 | dest='cmdline', type=str, 113 | default=None, 114 | help="Override the default kernel command line in the linux config") 115 | parser.add_argument( '-I', '--initrd', 116 | dest='initrd', type=str, 117 | default=None, 118 | help="Override the default initrd in the linux config") 119 | parser.add_argument( '-U', '--uncompressed', 120 | dest='initrd_uncompressed', action='store_true', 121 | default=False, 122 | help="Do not compress the initrd for faster boot") 123 | parser.add_argument( '-L', '--link', 124 | dest='symlinks', action='append', 125 | default=[], 126 | help="Symlinks to add to the build tree for external code dir=../real") 127 | parser.add_argument('--configure', 128 | dest='configure', type=str, 129 | default=None, 130 | help="Override the default Linux kernel oldconfig command (will be run in output directory") 131 | parser.add_argument('--url', 132 | dest='url', type=str, 133 | default=None, 134 | help="Override the default Linux kernel URL path") 135 | parser.add_argument('-N', '--name', 136 | dest='name', type=str, 137 | default='linux', 138 | help="Override the default Linux prefix for directory names") 139 | parser.add_argument('--no-kernel', 140 | dest='no_kernel', action='store_true', 141 | default=False, 142 | help="Do not try to extract the vmlinux") 143 | parser.add_argument('--targets', 144 | dest='make_target', type=str, 145 | default='', 146 | help="Target for make to build") 147 | 148 | args = parser.parse_args() 149 | version = args.version 150 | verbose = args.verbose 151 | config_file = args.config 152 | patch_files = args.patches 153 | output_dir = args.output_dir 154 | src_dir = args.src_dir 155 | ftp_dir = args.ftp_dir 156 | make_jobs = args.make_jobs 157 | kernel_hash = args.hash 158 | 159 | # split it into words following shell semantics 160 | make = shlex.split(make) 161 | 162 | # ensure that the config exists, 163 | # TODO: unless this is a menuconfig which might be creating from scratch 164 | if not exists(config_file): 165 | die(config_file + ": config file does not exist?") 166 | 167 | # Read the base configuration (may be updated later) 168 | # TODO: handle non-existant file for menuconfig 169 | (config, config_hash) = readfile(config_file) 170 | 171 | major = version.split('.')[0] 172 | tag = '' 173 | if args.tag: 174 | tag = "-" + args.tag 175 | patch_tag = '' 176 | patches = [] 177 | if patch_files: 178 | patch_data = b'' 179 | for patch_file in patch_files: 180 | if not exists(patch_file): 181 | die(patch_file + ": patch file does not exist?") 182 | (data, file_hash) = readfile(patch_file) 183 | patches.append([patch_file, data]) 184 | patch_data += data 185 | # compute the hash over all of the patches in order 186 | # and use the short form for the directory name 187 | patch_hash = hashlib.sha256(data).hexdigest() 188 | patch_tag = "-" + patch_hash[0:8] 189 | 190 | prefix = args.name + "-" 191 | 192 | if args.url: 193 | linux_url = args.url 194 | else: 195 | linux_url_base = "https://cdn.kernel.org/pub/linux/kernel/v%s.x/linux-%s" % (major, version) 196 | linux_url = linux_url_base + ".tar.xz" 197 | linux_sig = linux_url_base + ".tar.sign" 198 | linux_tar = os.path.join(ftp_dir, prefix + version + ".tar.xz") 199 | linux_dir = os.path.join(src_dir, prefix + version + patch_tag) 200 | build_dir = os.path.join(output_dir, prefix + version + tag) 201 | 202 | abs_build = os.path.abspath(build_dir) 203 | abs_linux = os.path.abspath(linux_dir) 204 | build_rdir = os.path.relpath(abs_build, abs_linux) 205 | 206 | kconfig_file = os.path.join(build_dir, ".config") 207 | kernel_file = os.path.join(output_dir, "vmlinuz" + tag) 208 | 209 | if verbose > 1: 210 | print("URL = " + linux_url) 211 | print("source = " + linux_dir) 212 | print("build = " + build_dir) 213 | print("kconfig = " + kconfig_file) 214 | print("tag = " + tag) 215 | if kernel_hash is not None: 216 | print("hash = " + kernel_hash) 217 | 218 | if args.clean: 219 | print("Removing " + linux_dir + " and " + build_dir, file=sys.stderr) 220 | system("rm", "-rf", linux_dir, build_dir) 221 | exit(0) 222 | 223 | unpack_canary = os.path.join(linux_dir, ".unpacked") 224 | patch_canary = os.path.join(linux_dir, ".patched") 225 | symlink_canary = os.path.join(linux_dir, ".symlinks") 226 | config_canary = os.path.join(build_dir, ".configured") 227 | build_canary = os.path.join(build_dir, ".built") 228 | 229 | if not os.path.exists(ftp_dir): 230 | info("Creating ftp dir " + ftp_dir) 231 | os.makedirs(ftp_dir, exist_ok=True) 232 | if not os.path.exists(src_dir): 233 | info("Creating src dir " + src_dir) 234 | os.makedirs(src_dir, exist_ok=True) 235 | if not os.path.exists(build_dir): 236 | info("Creating build dir " + build_dir) 237 | os.makedirs(build_dir, exist_ok=True) 238 | 239 | if not exists(linux_tar): 240 | info(linux_url + ": fetching") 241 | tmpfile = linux_tar + ".tmp" 242 | system("wget", "--no-verbose", "-O", tmpfile, linux_url) 243 | if kernel_hash is not None: 244 | (data,actual_hash) = readfile(tmpfile) 245 | if actual_hash != kernel_hash: 246 | die(linux_tar + ": " + actual_hash + " != expected " + kernel_hash) 247 | system("mv", tmpfile, linux_tar) 248 | 249 | if not exists(unpack_canary): 250 | info(linux_tar + ": unpacking into " + linux_dir) 251 | os.makedirs(linux_dir, exist_ok=True) 252 | system("tar", 253 | "-xf", linux_tar, 254 | "-C", linux_dir, 255 | "--strip-components", "1", 256 | ) 257 | 258 | writefile(unpack_canary, b'') 259 | 260 | if len(patches) != 0: 261 | if exists(patch_canary): 262 | (oldpatch_hash,hashhash) = readfile(patch_canary) 263 | if oldpatch_hash != patch_hash.encode('utf-8'): 264 | die(patch_file + ": wrong patch applied! delete source directory " + linux_dir + " and try again", patch_hash, oldpatch_hash) 265 | else: 266 | for patch in patches: 267 | # since patch chdir into the linux_dir, 268 | # we need an absolute path to the patch 269 | info(patch[0] + ": applying patch to " + linux_dir) 270 | with NamedTemporaryFile() as tmp: 271 | tmp.write(patch[1]) 272 | tmp.flush() 273 | system("patch", 274 | "--input", tmp.name, 275 | "--directory", linux_dir, 276 | "-p1", 277 | ) 278 | writefile(patch_canary, patch_hash.encode('utf-8')) 279 | 280 | if not exists(symlink_canary): 281 | for symlink in args.symlinks: 282 | (src,dest) = symlink.split('=') 283 | src = os.path.join(linux_dir, src) 284 | info("symlink " + src + " => " + dest) 285 | system("ln", "-s", dest, src) 286 | writefile(symlink_canary, b'') 287 | 288 | if args.menuconfig: 289 | # just in case this is the very first time, allow an empty config file 290 | # and pre-create the directory 291 | # re-write the config with the unmodified version 292 | writefile(kconfig_file, config) 293 | system(*make, 294 | "-j1", 295 | "-C", linux_dir, 296 | "O=" + build_rdir, 297 | "menuconfig", 298 | "savedefconfig" 299 | ) 300 | system("cp", 301 | os.path.join(build_dir,"defconfig"), 302 | config_file, 303 | ) 304 | exit(0) 305 | 306 | # Update the config with any overrides and recompute the hash 307 | if args.hostname is not None: 308 | hostname = args.hostname.encode('utf-8') 309 | config += b'CONFIG_DEFAULT_HOSTNAME="' + hostname + b'"\n' 310 | if args.initrd is not None: 311 | # the initrd might be a relative path to the invocation, 312 | # so make it absolute since the kernel will be built with make -C 313 | initrd = os.path.abspath(args.initrd).encode('utf-8') 314 | config += b'CONFIG_INITRAMFS_SOURCE="' + initrd + b'"\n' 315 | if args.initrd_uncompressed: 316 | # boots about 2 seconds faster 317 | config += b'CONFIG_INITRAMFS_COMPRESSION_NONE=y\n' 318 | if args.cmdline is not None: 319 | cmdline = args.cmdline.encode('utf-8') 320 | config += b'CONFIG_CMDLINE_BOOL=y\n' 321 | config += b'CONFIG_CMDLINE="' + cmdline + b'"\n' 322 | 323 | # recompute the hash 324 | config_hash = hashlib.sha256(config).hexdigest() 325 | 326 | # check to see if we need to reconfigure 327 | reconfig = False 328 | if exists(config_canary): 329 | # check to see if the parameters are the same 330 | (oldconfig_hash,hashhash) = readfile(config_canary) 331 | if os.stat(config_canary).st_mtime < os.stat(config_file).st_mtime: 332 | # they have touched the local config, force a reconfig 333 | reconfig = True 334 | if oldconfig_hash != config_hash.encode('utf-8'): 335 | reconfig = True 336 | else: 337 | # no canary, force a reconfiguration 338 | reconfig = True 339 | 340 | 341 | # export some variables 342 | os.environ['O'] = build_rdir 343 | 344 | if reconfig: 345 | info(kconfig_file + ": rebuilding kernel config") 346 | os.makedirs(build_dir, exist_ok=True) 347 | writefile(kconfig_file, config) 348 | 349 | if args.configure is None: 350 | system(*make, 351 | "-j1", 352 | "-C", linux_dir, 353 | "O=" + build_rdir, 354 | "olddefconfig" 355 | ) 356 | else: 357 | system( 358 | *shlex.split(args.configure), 359 | cwd=linux_dir 360 | ) 361 | 362 | writefile(config_canary, config_hash.encode('utf-8')) 363 | 364 | 365 | # finally ready to build! (in the build dir) 366 | make_cmd = [ *make, 367 | "KBUILD_BUILD_HOST=builder", 368 | "KBUILD_BUILD_USER=builder", 369 | "KBUILD_BUILD_TIMESTAMP=" + config_hash, 370 | "KBUILD_BUILD_VERSION=" + tag + patch_tag, 371 | "-C", build_dir, 372 | *shlex.split(args.make_target) 373 | #"O=" + build_rdir, 374 | ] 375 | 376 | if make_jobs: 377 | make_cmd.append("-j" + str(make_jobs)) 378 | if verbose > 3: 379 | make_cmd.append("V=1") 380 | 381 | info(build_dir + ": starting build") 382 | debug(make_cmd) 383 | 384 | system(*make_cmd) 385 | 386 | writefile(build_canary, b'') 387 | 388 | if args.no_kernel: 389 | sys.exit(0) 390 | 391 | (kernel, kernel_hash) = readfile(os.path.join(build_dir, "arch", "x86", "boot", "bzImage")) 392 | 393 | writefile(kernel_file, kernel) 394 | 395 | if verbose > 0: 396 | print("%s: %s" % (kernel_file, kernel_hash)) 397 | -------------------------------------------------------------------------------- /localcompile.py: -------------------------------------------------------------------------------- 1 | # Use the local gcc instead of building a cross compiler 2 | # 3 | import worldbuilder 4 | 5 | target_arch = "x86_64-linux-gnu" 6 | 7 | binutils = worldbuilder.Submodule("binutils", 8 | version = "usrbin", 9 | install_dir = "/usr", 10 | ) 11 | 12 | gcc = worldbuilder.Submodule("gcc", 13 | version = "usrbin", 14 | install_dir = "/usr/bin", 15 | ) 16 | 17 | 18 | cross = "/usr/bin/" 19 | 20 | # these are for gcc's special "FOO_FOR_TARGET" instead of "FOO" 21 | gcc_cross_tools = [x.upper() + "_FOR_TARGET=" + cross + x 22 | for x in "ar as ld nm ranlib objcopy objdump strip".split(" ")] 23 | 24 | cross_tools_nocc = [x.upper() + "=" + cross + x 25 | for x in "ar as ld nm ranlib objcopy objdump strip".split(" ")] 26 | 27 | cross_tools = [ 28 | "CC=gcc", 29 | "CXX=g++", 30 | *cross_tools_nocc, 31 | ] 32 | -------------------------------------------------------------------------------- /modules/busybox: -------------------------------------------------------------------------------- 1 | # busybox defaults `BB_EXTRA_VERSION` to the autoconf timestamp, 2 | # so it is necessary to pass in a fixed string to make it 3 | # reproducible. 4 | 5 | busybox_cflags = 'CFLAGS=' \ 6 | + '-DBB_EXTRA_VERSION=\'"%(out_hash)s"\' ' \ 7 | + '-I%(linux.inc_dir)s ' \ 8 | + commands.prefix_map \ 9 | 10 | worldbuilder.Submodule("busybox", 11 | depends = [ "gcc", "linux" ], 12 | url = "https://busybox.net/downloads/busybox-%(version)s.tar.bz2", 13 | version = "1.32.0", 14 | tarhash = "c35d87f1d04b2b153d33c275c2632e40d388a88f19a9e71727e0bbbff51fe689", 15 | config_files = [ "config/busybox.config" ], 16 | #patches = [ "patches/busybox-1.28.0.patch" ], 17 | configure = [ 18 | "make", 19 | "-C%(src_dir)s", 20 | "O=%(rout_dir)s", 21 | "oldconfig", 22 | *cross_tools, 23 | busybox_cflags, 24 | ], 25 | make = [ 26 | *commands.kbuild_make, 27 | "V=1", 28 | *cross_tools, 29 | busybox_cflags, 30 | ], 31 | install = [ 32 | [ "cp", "busybox", "%(install_dir)s" ], 33 | ], 34 | bin_dir = '', 35 | 36 | bins = [ "busybox" ], 37 | ) 38 | -------------------------------------------------------------------------------- /modules/cairo: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("cairo", 2 | depends = [ "pixman", "libpng", "gcc" ], 3 | version = "1.14.12", 4 | url = "https://www.cairographics.org/releases/cairo-%(version)s.tar.xz", 5 | tarhash = "8c90f00c500b2299c0a323dd9beead2a00353752b2092ead558139bd67f7bf16", 6 | 7 | patches = [ 8 | "patches/cairo-%(version)s.patch", # fixup call to pkg-config 9 | ], 10 | 11 | configure = [ [ 12 | commands.configure_cmd, 13 | "--prefix=/", 14 | "--host=x86_64-linux-gnu", 15 | "--target=" + target_arch, 16 | "--disable-xlib", 17 | "--disable-xcb", 18 | "--disable-pdf", 19 | "--disable-ps", 20 | "--disable-svg", 21 | "--disable-script", 22 | "--disable-ft", 23 | "--disable-fc", 24 | "--disable-pthread", 25 | "--disable-gobject", 26 | "CFLAGS=-DCAIRO_NO_MUTEX=1 -O3 " 27 | + "-I%(pixman.inc_dir)s " 28 | + "-I%(libpng.inc_dir)s " 29 | + "-I%(zlib.inc_dir)s " 30 | + commands.prefix_map, 31 | "LDFLAGS=" 32 | + "-L%(pixman.lib_dir)s -lpixman-1 " 33 | + "-L%(libpng.lib_dir)s -lpng16 " 34 | + "-L%(zlib.lib_dir)s -lz ", 35 | *cross_tools, 36 | "PKG_CONFIG=/bin/true", # otherwise it complains 37 | ], 38 | commands.fix_libtool, 39 | ], 40 | 41 | make = [ 42 | [ "make", "V=1" ], 43 | ], 44 | 45 | install = [ 46 | [ "make", "install", "DESTDIR=%(install_dir)s" ], 47 | commands.delete_la, 48 | commands.strip_libs, 49 | ], 50 | 51 | libs = [ "libcairo.so.2" ], 52 | ) 53 | 54 | -------------------------------------------------------------------------------- /modules/cryptsetup: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("cryptsetup", 2 | depends = [ "util-linux", "popt", "lvm2", "gcc" ], 3 | version = "1.7.3", 4 | url = 'https://www.kernel.org/pub/linux/utils/cryptsetup/v%(major)s.%(minor)s/cryptsetup-%(version)s.tar.xz', 5 | tarhash = 'af2b04e8475cf40b8d9ffd97a1acfa73aa787c890430afd89804fb544d6adc02', 6 | patches = [ "patches/cryptsetup-%(version)s.patch" ], 7 | 8 | configure = [ 9 | commands.configure_cmd, 10 | "--prefix=/", 11 | "--host=x86_64-linux-gnu", 12 | "--disable-rpath", 13 | "--disable-gcrypt-pbkdf2", 14 | "--enable-cryptsetup-reencrypt", 15 | "--with-crypto_backend=kernel", 16 | *cross_tools, 17 | "CFLAGS=-I%(util-linux.inc_dir)s -I%(lvm2.inc_dir)s -I%(linux.inc_dir)s -I%(popt.inc_dir)s " + commands.prefix_map, 18 | "LDFLAGS=-L%(util-linux.lib_dir)s -L%(popt.lib_dir)s", 19 | "DEVMAPPER_CFLAGS=-I%(lvm2.inc_dir)s", 20 | "DEVMAPPER_LIBS=-L%(lvm2.lib_dir)s -ldevmapper", 21 | ], 22 | 23 | make = [ "make", "all", "V=1" ], 24 | 25 | install = [ "make", "install", "DESTDIR=%(install_dir)s", ], 26 | 27 | bin_dir = "sbin", 28 | 29 | bins = [ "cryptsetup", "veritysetup", "cryptsetup-reencrypt" ], 30 | libs = [ "libcryptsetup.so.4" ], 31 | 32 | ) 33 | -------------------------------------------------------------------------------- /modules/cryptsetup2: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("cryptsetup2", 2 | depends = [ "util-linux", "popt", "lvm2", "json-c", "gcc" ], 3 | version = "2.3.3", 4 | url = "https://www.kernel.org/pub/linux/utils/cryptsetup/v%(major)s.%(minor)s/cryptsetup-%(version)s.tar.xz", 5 | tarhash = "3bca4ffe39e2f94cef50f6ea65acb873a6dbce5db34fc6bcefe38b6d095e82df", 6 | 7 | configure = [ [ 8 | commands.configure_cmd, 9 | "--host=x86_64-gnu-linux", 10 | "--target=" + target_arch, 11 | "--prefix=/", 12 | "--disable-rpath", 13 | "--disable-gcrypt-pbkdf2", 14 | "--enable-cryptsetup-reencrypt", 15 | "--with-crypto_backend=kernel", 16 | "--with-tmpfilesdir=%(install_dir)s/lib/tmpfiles.d", 17 | *cross_tools, 18 | "PKG_CONFIG=/bin/true", 19 | "CFLAGS=" 20 | + "-I%(util-linux.inc_dir)s " 21 | + "-I%(lvm2.inc_dir)s " 22 | + "-I%(linux.inc_dir)s " 23 | + "-I%(popt.inc_dir)s " 24 | + "-I%(json-c.inc_dir)s " 25 | + commands.prefix_map, 26 | "LDFLAGS=" 27 | + "-L%(lvm2.lib_dir)s -ldevmapper " 28 | + "-L%(json-c.lib_dir)s -ljson-c " 29 | + "-L%(util-linux.lib_dir)s -lblkid -luuid " 30 | + "-L%(popt.lib_dir)s -lpopt " 31 | + "", 32 | ], 33 | commands.fix_libtool, 34 | ], 35 | 36 | make = [ "make" ], 37 | 38 | install = [ 39 | [ "make", "install", "DESTDIR=%(install_dir)s" ], 40 | commands.delete_la, 41 | commands.strip_libs, 42 | ], 43 | 44 | bin_dir = "sbin", 45 | bins = [ "cryptsetup", "cryptsetup-reencrypt", "veritysetup" ], 46 | libs = [ "libcryptsetup.so.12" ], 47 | ) 48 | 49 | -------------------------------------------------------------------------------- /modules/dropbear: -------------------------------------------------------------------------------- 1 | # dropbear is a tiny ssh client 2 | worldbuilder.Submodule("dropbear", 3 | depends = [ "zlib", "linux", "gcc" ], 4 | version = "2016.74", 5 | url = "https://matt.ucc.asn.au/dropbear/releases/dropbear-%(version)s.tar.bz2", 6 | tarhash = "2720ea54ed009af812701bcc290a2a601d5c107d12993e5d92c0f5f81f718891", 7 | patches = [ "patches/dropbear-%(version)s.patch", ], 8 | 9 | configure = [ 10 | commands.configure_cmd, 11 | "--prefix=%(install_dir)s", 12 | "--host=x86_64-linux-gnu", 13 | "--disable-syslog", 14 | "--disable-lastlog", 15 | "--disable-utmp", 16 | "--disable-utmpx", 17 | "--disable-wtmp", 18 | "--disable-wtmpx", 19 | "--with-zlib=%(zlib.install_dir)s", 20 | "CFLAGS=-I%(linux.inc_dir)s -I%(out_dir)s -I%(src_dir)s -I%(src_dir)s/libtommath " + commands.prefix_map, 21 | *cross_tools, 22 | ], 23 | make = [ 24 | "make", 25 | #"DESTDIR=install", 26 | "dbclient", 27 | "scp", 28 | "dropbear", 29 | ], 30 | install = [ 31 | [ "make", "install" ], 32 | # strip to remove explict paths to libgcc and rename executables 33 | [ cross+"strip", "-o", "%(bin_dir)s/ssh", "%(bin_dir)s/dbclient" ], 34 | [ cross+"strip", "-o", "%(bin_dir)s/sshd", "%(install_dir)s/sbin/dropbear" ], 35 | ], 36 | 37 | bins = [ "ssh", "sshd" ], 38 | ) 39 | -------------------------------------------------------------------------------- /modules/fbwhiptail: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("fbwhiptail", 2 | depends = [ "cairo", "pixman", "libpng", "zlib", "linux", "gcc" ], 3 | version = "0f14a409735b71c219e0b9b3ee63cdae709ba143", 4 | url = "https://source.puri.sm/coreboot/fbwhiptail/-/archive/%(version)s/fbwhiptail-%(version)s.tar.gz", 5 | tarhash = "d664cad8a5bd5354258809a642b717c46c5b7b9e797c6275b9d6494986ad0f15", 6 | patches = [ "patches/fbwhiptail.patch" ], 7 | dirty = True, 8 | 9 | make = [ 10 | "make", 11 | "fbwhiptail", 12 | *cross_tools, 13 | "CFLAGS=" 14 | + " -I%(cairo.inc_dir)s" 15 | + " -I%(linux.inc_dir)s" 16 | + " -L%(cairo.lib_dir)s" 17 | + " -L%(pixman.lib_dir)s" 18 | + " -L%(libpng.lib_dir)s" 19 | + " -L%(zlib.lib_dir)s" 20 | + " " + commands.prefix_map, 21 | ], 22 | 23 | install = [ 24 | "cp", "whiptail", "fbwhiptail", "%(install_dir)s", 25 | ], 26 | bin_dir = "", 27 | bins = [ "whiptail", "fbwhiptail" ], 28 | ) 29 | -------------------------------------------------------------------------------- /modules/flashrom: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("flashrom", 2 | depends = [ "pciutils", "zlib", "gcc" ], 3 | version = "b1f858f65b2abd276542650d8cb9e382da258967", 4 | url = "https://github.com/flashrom/flashrom/archive/%(version)s.tar.gz", 5 | tarhash = "4873ad50f500629c244fc3fbee64b56403a82307d7f555dfa235336a200c336c", 6 | dirty = True, 7 | patches = [ "patches/flashrom-0100-enable-kgpe-d16.patch", ], 8 | 9 | make = [ "make", 10 | "WARNERROR=no", 11 | "CONFIG_NOTHING=yes", 12 | "CONFIG_INTERNAL=yes", 13 | "CONFIG_DUMMY=yes", 14 | "CONFIG_AST1100=yes", 15 | "CFLAGS=-O3 -W -Wall -I%(pciutils.inc_dir)s -I%(zlib.inc_dir)s " + commands.prefix_map, 16 | "LDFLAGS=-L%(pciutils.lib_dir)s -L%(zlib.lib_dir)s", 17 | *cross_tools, 18 | ], 19 | 20 | install = [ 21 | [ "mkdir", "-p", "%(bin_dir)s" ], 22 | [ cross + "strip", "-o", "%(bin_dir)s/flashrom", "%(out_dir)s/flashrom" ], 23 | ], 24 | 25 | bins = [ "flashrom" ], 26 | ) 27 | -------------------------------------------------------------------------------- /modules/iasl: -------------------------------------------------------------------------------- 1 | # this is a host_cc, not a cross compiled program 2 | # it only uses crossgcc to get the version number to report 3 | # to coreboot that queries it. 4 | 5 | worldbuilder.Submodule("iasl", 6 | depends = [ "crossgcc_src" ], 7 | version = "20210331", 8 | url = "https://acpica.org/sites/acpica/files/acpica-unix2-%(version)s.tar.gz", 9 | tarhash = "3dab326c262d4f3eaf380bbbbd7aa8c2eb5f2697f7821659222cf898d8be28c1", 10 | dirty = True, # writes into a ./obj directory 11 | patches = [ "patches/acpica-unix2-%(version)s_iasl.patch" ], 12 | make = [ "make", 13 | "OPT_CFLAGS=-O -D_FORTIFY_SOURCE=2 -D COREBOOT_TOOLCHAIN_VERSION='\"coreboot toolchain v%(crossgcc_src.version)s\"'", 14 | ], 15 | 16 | install = [ 17 | #"make", "DESTDIR=%(install_dir)s", "install", 18 | [ "mkdir", "-p", "%(bin_dir)s" ], 19 | [ "cp", "generate/unix/bin/iasl", "%(bin_dir)s/", ], 20 | ], 21 | 22 | #bin_dir = "bin", 23 | ) 24 | -------------------------------------------------------------------------------- /modules/json-c: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("json-c", 2 | depends = [ "gcc" ], 3 | version = "0.14", 4 | url = "https://s3.amazonaws.com/json-c_releases/releases/json-c-%(version)s-nodoc.tar.gz", 5 | tarhash = "99914e644a25201d82ccefa20430f7515c110923360f9ef46755527c02412afa", 6 | 7 | # there is a bug in cmake-configure so that it can not be used with a "=", fxed in next 8 | # release though (then it needs to read '--prefix="$(INSTALL)"' here instead 9 | kconfig_file = "toolchain", 10 | 11 | config_append = [ 12 | "set(CMAKE_SYSTEM_NAME Linux)", 13 | "set(CMAKE_SYSROOT %(install_dir)s)", 14 | "set(CMAKE_C_COMPILER "+cross_gcc+")", 15 | "set(CMAKE_AR "+cross+"ar)", 16 | "set(CMAKE_LINKER "+cross+"ld)", 17 | "set(CMAKE_NM "+cross+"nm)", 18 | "set(CMAKE_OBJCOPY "+cross+"objcopy)", 19 | "set(CMAKE_OBJDUMP "+cross+"objdump)", 20 | "set(INSTALL_PKGCONFIG_DIR %(install_dir)s/lib/pkgconfig)", 21 | "set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)", 22 | "set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)", 23 | "set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)", 24 | "set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)", 25 | 'set(CMAKE_C_FLAGS "' + commands.prefix_map + '")', 26 | ], 27 | 28 | configure = [ 29 | "cmake", 30 | "%(src_dir)s", 31 | "-DCMAKE_INSTALL_PREFIX=%(install_dir)s", 32 | "-DCMAKE_TOOLCHAIN_FILE=toolchain", 33 | ], 34 | 35 | make = [ 36 | "make", 37 | "all", 38 | "V=1", 39 | *cross_tools, 40 | ], 41 | 42 | install = [ 43 | "make", 44 | "install", 45 | ], 46 | 47 | libs = [ "libjson-c.so.5" ], 48 | ) 49 | -------------------------------------------------------------------------------- /modules/kexec: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule('kexec', 2 | version = '2.0.20', 3 | url = 'https://kernel.org/pub/linux/utils/kernel/kexec/kexec-tools-%(version)s.tar.gz', 4 | tarhash = 'cb16d79818e0c9de3bb3e33ede5677c34a1d28c646379c7ab44e0faa3eb57a16', 5 | patches = [ 6 | "patches/kexec-2.0.20.patch", 7 | "patches/kexec-2.0.20-duplicate-symbols.patch", 8 | ], 9 | depends = [ "linux", "gcc" ], 10 | configure = [ 11 | commands.configure_cmd, 12 | "--prefix=%(install_dir)s", 13 | "--host", 'x86_64-linux-gnu', #'i386-elf-linux', 14 | "--target", 'x86_64', 15 | "--without-lzma", 16 | *cross_tools, 17 | "CFLAGS=-I%(linux.inc_dir)s " + commands.prefix_map, 18 | ], 19 | make = [ "make" ], 20 | install = [ "make", "install" ], 21 | bin_dir = 'sbin', 22 | 23 | bins = [ "kexec" ], 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /modules/libpng: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("libpng", 2 | depends = [ "zlib", "gcc" ], 3 | version = "1.6.34", 4 | url = "https://github.com/glennrp/libpng-releases/raw/master/libpng-%(version)s.tar.gz", 5 | tarhash = "574623a4901a9969080ab4a2df9437026c8a87150dfd5c235e28c94b212964a7", 6 | 7 | configure = [ [ 8 | commands.configure_cmd, 9 | "--prefix=/", 10 | "--host=x86_64-linux-gnu", 11 | "CFLAGS=-I%(zlib.inc_dir)s " + commands.prefix_map, 12 | "CPPFLAGS=-I%(zlib.inc_dir)s " + commands.prefix_map, 13 | "LDFLAGS=-L%(zlib.lib_dir)s", 14 | *cross_tools, 15 | ], 16 | commands.fix_libtool, 17 | ], 18 | 19 | make = [ "make" ], 20 | 21 | install = [ 22 | [ "make", "install", "DESTDIR=%(install_dir)s" ], 23 | commands.delete_la, 24 | ], 25 | 26 | libs = [ "libpng16.so.16" ], 27 | ) 28 | -------------------------------------------------------------------------------- /modules/lvm2: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("lvm2", 2 | depends = [ "util-linux", "gcc" ], 3 | version = "2.02.168", 4 | url = "https://mirrors.kernel.org/sourceware/lvm2/LVM2.%(version)s.tgz", 5 | tarhash = "23a3d1cddd41b3ef51812ebf83e9fa491f502fe74130d4263be327a91914660d", 6 | patches = [ "patches/lvm2-%(version)s/*.patch", ], 7 | 8 | configure = [ 9 | commands.configure_cmd, 10 | "--prefix=/", 11 | "MODPROBE_CMD=/bin/false", 12 | "ac_cv_func_malloc_0_nonnull=yes", 13 | "ac_cv_func_realloc_0_nonnull=yes", 14 | "--host=i386-elf-linux", 15 | "--enable-devmapper", 16 | "--disable-selinux", 17 | "--disable-udev-systemd-background-jobs", 18 | "--disable-realtime", 19 | "--disable-dmeventd", 20 | "--disable-lvmetad", 21 | "--disable-lvmpolld", 22 | "--disable-use-lvmlockd", 23 | "--disable-use-lvmetad", 24 | "--disable-use-lvmpolld", 25 | "--disable-blkid_wiping", 26 | "--disable-cmirrord", 27 | "--disable-cache_check_needs_check", 28 | "--disable-thin_check_needs_check", 29 | "--with-cluster=none", 30 | "CFLAGS=-fPIC -I%(linux.inc_dir)s " + commands.prefix_map, 31 | *cross_tools, 32 | ], 33 | 34 | make = [ 35 | "make", 36 | "all", 37 | "CFLAGS=-fPIC -I%(linux.inc_dir)s " + commands.prefix_map, 38 | *cross_tools, 39 | ], 40 | 41 | install = [ 42 | "make", 43 | "install_device-mapper", 44 | "install_lvm2", 45 | "DESTDIR=%(install_dir)s", 46 | *cross_tools, 47 | ], 48 | 49 | bin_dir = "sbin", 50 | bins = [ "dmsetup", "lvm" ], 51 | libs = [ "libdevmapper.so.1.02" ], 52 | ) 53 | -------------------------------------------------------------------------------- /modules/newt: -------------------------------------------------------------------------------- 1 | # 2 | # This is mutually exclusive with fbwhiptail 3 | # 4 | worldbuilder.Submodule("newt", 5 | depends = [ "slang", "popt", "gcc" ], 6 | version = "0.52.20", 7 | url = "https://releases.pagure.org/newt/newt-%(version)s.tar.gz", 8 | tarhash = "8d66ba6beffc3f786d4ccfee9d2b43d93484680ef8db9397a4fb70b5adbb6dbc", 9 | dirty = True, # Makefile isn't written to read from external source directory 10 | 11 | configure = [ 12 | commands.configure_cmd, 13 | "--prefix=%(install_dir)s", 14 | "--host=x86_64-linux-gnu", 15 | "--without-tcl", 16 | "CFLAGS=-I%(slang.inc_dir)s -I%(popt.inc_dir)s " + commands.prefix_map, 17 | "LDFLAGS=-L%(slang.lib_dir)s -L%(popt.lib_dir)s", 18 | *cross_tools, 19 | ], 20 | 21 | make = [ "make", "whiptail" ], 22 | 23 | install = [ "make", "install" ], 24 | 25 | bins = [ "whiptail" ], 26 | libs = [ "libnewt.so.0.52" ], 27 | ) 28 | -------------------------------------------------------------------------------- /modules/openssh: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("openssh", 2 | depends = [ "openssl", "zlib", "gcc" ], 3 | version = "8.9p1", 4 | url = "https://mirror.laylo.io/pub/OpenBSD/OpenSSH/portable/openssh-%(version)s.tar.gz", 5 | tarhash = "fd497654b7ab1686dac672fb83dfb4ba4096e8b5ffcdaccd262380ae58bec5e7", 6 | configure = [ 7 | commands.configure_cmd, 8 | #"--prefix=%(install_dir)s", # the install makefile uses DESTDIR instead 9 | "--prefix=/", 10 | "--target=" + target_arch, 11 | "--host=x86_64-linux-gnu", 12 | "--with-zlib=%(zlib.install_dir)s", 13 | "--with-openssl=%(openssl.install_dir)s", 14 | "CFLAGS=-I%(openssl.inc_dir)s " + commands.prefix_map, 15 | "LDFLAGS=-L%(openssl.lib_dir)s", 16 | *cross_tools, 17 | ], 18 | # only install the binaries, not the system configuration stuff 19 | make = [ "make" ], 20 | install = [ "make", "-j1", "install-nosysconf", "DESTDIR=%(install_dir)s", ], 21 | ) 22 | -------------------------------------------------------------------------------- /modules/openssl: -------------------------------------------------------------------------------- 1 | from worldbuilder.util import quote 2 | 3 | worldbuilder.Submodule("openssl", 4 | depends = [ "zlib", "linux", "gcc" ], 5 | version = "1.1.1n", 6 | url = "https://www.openssl.org/source/openssl-%(version)s.tar.gz", 7 | tarhash = "40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a", 8 | dirty = True, 9 | configure = [ "bash", "-c", " ".join([ 10 | "CFLAGS=" + quote(commands.prefix_map), 11 | *cross_tools, 12 | "%(src_dir)s/Configure", 13 | "--prefix=%(install_dir)s", 14 | "--with-zlib-include=%(zlib.inc_dir)s", 15 | "--with-zlib-lib=%(zlib.lib_dir)s", 16 | #"--cross-compile-prefix=" + cross, 17 | "linux-x86_64", 18 | #"-I%(musl.inc_dir)s", 19 | "-I%(linux.inc_dir)s", 20 | #"-L%(binutils.lib_dir)s/gcc/"+target_arch+"/%(gcc.version)s", 21 | ]) ], 22 | make = [ "make" ], 23 | install = [ "make", "install" ], 24 | ) 25 | -------------------------------------------------------------------------------- /modules/pciutils: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("pciutils", 2 | depends = [ "gcc", "zlib", "linux" ], 3 | version = "3.5.4", 4 | url = "https://www.kernel.org/pub/software/utils/%(name)s/%(name)s-%(version)s.tar.xz", 5 | tarhash = "64293c6ab9318c40ef262b76d87bd9097531759752bac556e50979b1e63cfe66", 6 | patches = [ "patches/pciutils-%(version)s.patch" ], 7 | 8 | # the makefile writes in the source directory 9 | dirty = True, 10 | 11 | # IDSDIR must be set to a constant during the build, 12 | # but not during the install to make the libpci.so.3 13 | # reproducible. Otherwise the build path will be embedded 14 | # in the library and executables. 15 | make = [ 16 | "make", 17 | "ZLIB=yes", 18 | "HWDB=no", 19 | "LIBKMOD=no", 20 | "SHARED=yes", 21 | "IDSDIR=/", 22 | "PREFIX=/", 23 | *cross_tools, 24 | "CFLAGS=-fpic -I%(linux.inc_dir)s -I%(zlib.inc_dir)s " + commands.prefix_map, 25 | "LDFLAGS=-L%(zlib.lib_dir)s -lz", 26 | ], 27 | install = [ 28 | "make", 29 | "ZLIB=yes", 30 | "HWDB=no", 31 | "LIBKMOD=no", 32 | "SHARED=yes", 33 | "PREFIX=/", 34 | "DESTDIR=%(install_dir)s", 35 | "install", 36 | "install-lib", 37 | ], 38 | 39 | bin_dir = "sbin", 40 | bins = [ "lspci" ], 41 | libs = [ "libpci.so.3.5.4" ], 42 | ) 43 | 44 | -------------------------------------------------------------------------------- /modules/pixman: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("pixman", 2 | depends = [ "libpng", "zlib", "gcc" ], 3 | version = "0.34.0", 4 | url = 'https://www.cairographics.org/releases/pixman-%(version)s.tar.gz', 5 | tarhash = '21b6b249b51c6800dc9553b65106e1e37d0e25df942c90531d4c3997aa20a88e', 6 | 7 | configure = [ [ 8 | commands.configure_cmd, 9 | "--prefix=/", 10 | "--host=x86_64-linux-gnu", 11 | "--target=" + target_arch, 12 | "--disable-gtk", 13 | *cross_tools, 14 | "CFLAGS=-I%(libpng.inc_dir)s -I%(zlib.inc_dir)s" + commands.prefix_map, 15 | "LDFLAGS=-L%(libpng.lib_dir)s -lpng16 -L%(zlib.lib_dir)s -lz", 16 | ], 17 | commands.fix_libtool, 18 | ], 19 | 20 | inc_dir = "include/pixman-1", 21 | 22 | make = [ 23 | [ "make", "V=1" ], 24 | ], 25 | 26 | install = [ 27 | [ "make", "install", "DESTDIR=%(install_dir)s", ], 28 | commands.delete_la, 29 | commands.strip_libs, 30 | ], 31 | 32 | libs = [ "libpixman-1.so.0" ], 33 | ) 34 | 35 | -------------------------------------------------------------------------------- /modules/popt: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("popt", 2 | depends = [ "gcc" ], 3 | version = "1.16", 4 | url = "https://launchpad.net/popt/head/%(version)s/+download/popt-%(version)s.tar.gz", 5 | tarhash = 'e728ed296fe9f069a0e005003c3d6b2dde3d9cad453422a10d6558616d304cc8', 6 | 7 | configure = [ [ 8 | commands.configure_cmd, 9 | "--prefix=/", 10 | "--host=x86_64-linux-gnu", 11 | "--disable-rpath", 12 | "CFLAGS=" + commands.prefix_map, 13 | *cross_tools, 14 | ], 15 | commands.fix_libtool, 16 | ], 17 | 18 | make = [ "make", *cross_tools ], 19 | 20 | install = [ 21 | [ "make", "install", "DESTDIR=%(install_dir)s" ], 22 | commands.delete_la, 23 | commands.strip_libs, 24 | ], 25 | 26 | libs = [ "libpopt.so.0" ], 27 | ) 28 | -------------------------------------------------------------------------------- /modules/slang: -------------------------------------------------------------------------------- 1 | # configure says "This software does not support configuring from another directory" 2 | 3 | worldbuilder.Submodule("slang", 4 | depends = [ "gcc" ], 5 | version = "2.3.1a", 6 | url = "https://www.jedsoft.org/releases/slang/slang-%(version)s.tar.bz2", 7 | tarhash = "54f0c3007fde918039c058965dffdfd6c5aec0bad0f4227192cc486021f08c36", 8 | dirty = True, 9 | configure = [ 10 | commands.configure_cmd, 11 | "--prefix=%(install_dir)s", 12 | "--host=x86_64-linux-gnu", 13 | "ac_cv_path_nc5config=no", 14 | "--with-z=no", 15 | "--with-png=no", 16 | "--with-pcre=no", 17 | "--with-onig=no", 18 | "CFLAGS=" + commands.prefix_map, 19 | *cross_tools, 20 | ], 21 | 22 | make = [ 23 | [ "mkdir", "-p", "src/elfobjs" ], 24 | [ "make" ], 25 | ], 26 | 27 | install = [ "make", "-j1", "install" ], # Disable parallel make for the install target 28 | 29 | libs = [ "libslang.so.2" ], 30 | ) 31 | -------------------------------------------------------------------------------- /modules/util-linux: -------------------------------------------------------------------------------- 1 | worldbuilder.Submodule("util-linux", 2 | version = "2.29.2", 3 | url = "https://www.kernel.org/pub/linux/utils/util-linux/v%(major)s.%(minor)s/util-linux-%(version)s.tar.xz", 4 | tarhash = "accea4d678209f97f634f40a93b7e9fcad5915d1f4749f6c47bee6bf110fe8e3", 5 | depends = [ "linux", "gcc" ], 6 | configure = [ 7 | commands.configure_cmd, 8 | "--prefix=%(install_dir)s", 9 | "--target", target_arch, 10 | "--host", 'x86_64-linux-gnu', 11 | "--without-ncurses", 12 | "--without-ncursesw", 13 | "--without-tinfo", 14 | "--without-udev", 15 | "--without-python", 16 | "--disable-bash-completion", 17 | "--disable-all-programs", 18 | "--enable-libuuid", 19 | "--enable-libblkid", 20 | *cross_tools, 21 | "CFLAGS=-I%(linux.inc_dir)s " + commands.prefix_map, 22 | ], 23 | make = [ "make" ], 24 | install = [ "make", "install" ], 25 | ) 26 | -------------------------------------------------------------------------------- /modules/zlib: -------------------------------------------------------------------------------- 1 | # zlib uses a non-standard `configure` script, so it is necessary 2 | # to pass special environment variables and build it in the same directory 3 | # as the source code. 4 | # 5 | # It also has a totally broken cross compiler detection that we have to 6 | # hack around to get the right compiler used 7 | 8 | worldbuilder.Submodule('zlib', 9 | depends = [ "gcc" ], 10 | version = '1.2.12', 11 | url = 'https://zlib.net/zlib-%(version)s.tar.gz', 12 | tarhash = '91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9', 13 | dirty = True, 14 | 15 | configure = [ 16 | # TODO: add way to pass env rather than invoking bash 17 | "bash", "-c", " ".join([ 18 | #"CROSS_PREFIX="+quote(cross), 19 | #"LDSHARED="+quote(cross+"gcc"), 20 | #*cross_tools, 21 | #"CFLAGS="+quote("-fPIC " + commands.prefix_map), 22 | commands.configure_cmd, 23 | "--prefix=%(install_dir)s" 24 | ]), 25 | ], 26 | 27 | # override the CC that they have determined during the configure stage 28 | # the actual gcc should have a proper name of some sort 29 | make = [ 30 | "make", 31 | "static", 32 | "libz.so.%(version)s", 33 | *cross_tools, 34 | "CFLAGS=" + commands.prefix_map, 35 | "LDSHARED=" + cross_gcc + " -shared", 36 | ], 37 | install = [ "make", "install", *cross_tools ], 38 | 39 | libs = [ "libz.so" ], 40 | ) 41 | -------------------------------------------------------------------------------- /patches/acpica-unix2-20210331_iasl.patch: -------------------------------------------------------------------------------- 1 | diff --git a/source/compiler/asloptions.c b/source/compiler/asloptions.c 2 | index 4bf9465ba..14c61a122 100644 3 | --- a/source/compiler/asloptions.c 4 | +++ b/source/compiler/asloptions.c 5 | @@ -234,6 +234,7 @@ AslCommandLine ( 6 | if (AslGbl_DoSignon) 7 | { 8 | printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); 9 | + printf ("%s\n", COREBOOT_TOOLCHAIN_VERSION); 10 | if (AslGbl_IgnoreErrors) 11 | { 12 | printf ("Ignoring all errors, forcing AML file generation\n\n"); 13 | @@ -866,6 +867,7 @@ AslDoOptions ( 14 | case '^': 15 | 16 | printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); 17 | + printf ("%s\n", COREBOOT_TOOLCHAIN_VERSION); 18 | exit (0); 19 | 20 | case 'a': 21 | @@ -879,6 +881,7 @@ AslDoOptions ( 22 | 23 | printf (ACPI_COMMON_SIGNON (ASL_COMPILER_NAME)); 24 | printf (ACPI_COMMON_BUILD_TIME); 25 | + printf ("%s\n", COREBOOT_TOOLCHAIN_VERSION); 26 | exit (0); 27 | 28 | case 'e': 29 | -------------------------------------------------------------------------------- /patches/cairo-1.14.12.patch: -------------------------------------------------------------------------------- 1 | --- ../../clean/cairo-1.14.12/configure 2017-12-06 22:50:48.000000000 +0000 2 | +++ 8c90f00c500b2299/configure 2022-03-31 16:13:16.718461113 +0000 3 | @@ -32840,7 +32840,7 @@ 4 | 5 | 6 | 7 | -if pkg-config --exists 'pixman-1 >= 0.27.1'; then 8 | +if ${PKG_CONFIG} -config --exists 'pixman-1 >= 0.27.1'; then 9 | 10 | $as_echo "#define HAS_PIXMAN_GLYPHS 1" >>confdefs.h 11 | 12 | -------------------------------------------------------------------------------- /patches/coreboot-4.13/0010-genbuild-iasl.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive ../../clean/coreboot-4.13/util/genbuild_h/genbuild_h.sh 683d5b969e75b346/util/genbuild_h/genbuild_h.sh 2 | --- ../../clean/coreboot-4.13/util/genbuild_h/genbuild_h.sh 2020-11-20 12:01:35.000000000 +0000 3 | +++ 683d5b969e75b346/util/genbuild_h/genbuild_h.sh 2022-04-01 18:56:21.820182853 +0000 4 | @@ -47,7 +47,9 @@ 5 | esac 6 | } 7 | 8 | -IASL=util/crossgcc/xgcc/bin/iasl 9 | +if [ -z "$IASL" ]; then 10 | + IASL=util/crossgcc/xgcc/bin/iasl 11 | +fi 12 | eval $(grep ^IASL:= "$XCOMPILE" 2>/dev/null | sed s,:=,=,) 13 | 14 | #Print out the information that goes into build.h 15 | diff -u --recursive ../../clean/coreboot-4.13/util/xcompile/xcompile 683d5b969e75b346/util/xcompile/xcompile 16 | --- ../../clean/coreboot-4.13/util/xcompile/xcompile 2020-11-20 12:01:35.000000000 +0000 17 | +++ 683d5b969e75b346/util/xcompile/xcompile 2022-04-01 18:57:19.255907428 +0000 18 | @@ -50,7 +50,9 @@ 19 | } 20 | 21 | 22 | -if [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 23 | +if [ -n "${IASL}" ]; then 24 | + true 25 | +elif [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 26 | IASL=${XGCCPATH}iasl 27 | elif [ "$(iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 28 | IASL=iasl 29 | -------------------------------------------------------------------------------- /patches/coreboot-4.13/0020-ld-nostartfiles.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive ../../clean/coreboot-4.13/Makefile.inc 683d5b969e75b346/Makefile.inc 2 | --- ../../clean/coreboot-4.13/Makefile.inc 2020-11-20 12:01:35.000000000 +0000 3 | +++ 683d5b969e75b346/Makefile.inc 2022-04-01 18:28:27.829549464 +0000 4 | @@ -485,7 +485,7 @@ 5 | # Disable style checks for now 6 | ADAFLAGS_common += -gnatyN 7 | 8 | -LDFLAGS_common := --gc-sections -nostdlib -nostartfiles -static --emit-relocs 9 | +LDFLAGS_common := --gc-sections -nostdlib -static --emit-relocs 10 | 11 | ifeq ($(CONFIG_WARNINGS_ARE_ERRORS),y) 12 | CFLAGS_common += -Werror 13 | -------------------------------------------------------------------------------- /patches/coreboot-4.13/0080-util-crossgcc-builgcc_temp_fix_from_https_to_http.patch: -------------------------------------------------------------------------------- 1 | --- a/util/crossgcc/buildgcc.orig 2021-01-03 19:56:28.980000000 -0500 2 | +++ b/util/crossgcc/buildgcc 2021-01-03 19:56:32.098000000 -0500 3 | @@ -52,22 +52,22 @@ 4 | # These are sanitized by the jenkins toolchain test builder, so if 5 | # a completely new URL is added here, it probably needs to be added 6 | # to the jenkins build as well, or the builder won't download it. 7 | -GMP_ARCHIVE="https://ftpmirror.gnu.org/gmp/gmp-${GMP_VERSION}.tar.xz" 8 | -MPFR_ARCHIVE="https://ftpmirror.gnu.org/mpfr/mpfr-${MPFR_VERSION}.tar.xz" 9 | -MPC_ARCHIVE="https://ftpmirror.gnu.org/mpc/mpc-${MPC_VERSION}.tar.gz" 10 | -GCC_ARCHIVE="https://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz" 11 | -BINUTILS_ARCHIVE="https://ftpmirror.gnu.org/binutils/binutils-${BINUTILS_VERSION}.tar.xz" 12 | -GDB_ARCHIVE="https://ftpmirror.gnu.org/gdb/gdb-${GDB_VERSION}.tar.xz" 13 | -IASL_ARCHIVE="https://acpica.org/sites/acpica/files/acpica-unix2-${IASL_VERSION}.tar.gz" 14 | -PYTHON_ARCHIVE="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz" 15 | -EXPAT_ARCHIVE="https://downloads.sourceforge.net/sourceforge/expat/expat-${EXPAT_VERSION}.tar.bz2" 16 | +GMP_ARCHIVE="http://ftpmirror.gnu.org/gmp/gmp-${GMP_VERSION}.tar.xz" 17 | +MPFR_ARCHIVE="http://ftpmirror.gnu.org/mpfr/mpfr-${MPFR_VERSION}.tar.xz" 18 | +MPC_ARCHIVE="http://ftpmirror.gnu.org/mpc/mpc-${MPC_VERSION}.tar.gz" 19 | +GCC_ARCHIVE="http://ftpmirror.gnu.org/gcc/gcc-${GCC_VERSION}/gcc-${GCC_VERSION}.tar.xz" 20 | +BINUTILS_ARCHIVE="http://ftpmirror.gnu.org/binutils/binutils-${BINUTILS_VERSION}.tar.xz" 21 | +GDB_ARCHIVE="http://ftpmirror.gnu.org/gdb/gdb-${GDB_VERSION}.tar.xz" 22 | +IASL_ARCHIVE="http://acpica.org/sites/acpica/files/acpica-unix2-${IASL_VERSION}.tar.gz" 23 | +PYTHON_ARCHIVE="http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz" 24 | +EXPAT_ARCHIVE="http://downloads.sourceforge.net/sourceforge/expat/expat-${EXPAT_VERSION}.tar.bz2" 25 | # CLANG toolchain archive locations 26 | -LLVM_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/llvm-${CLANG_VERSION}.src.tar.xz" 27 | -CLANG_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang-${CLANG_VERSION}.src.tar.xz" 28 | -CRT_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/compiler-rt-${CLANG_VERSION}.src.tar.xz" 29 | -CTE_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang-tools-extra-${CLANG_VERSION}.src.tar.xz" 30 | -CMAKE_ARCHIVE="https://cmake.org/files/v3.18/cmake-${CMAKE_VERSION}.tar.gz" 31 | -NASM_ARCHIVE="https://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.bz2" 32 | +LLVM_ARCHIVE="http://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/llvm-${CLANG_VERSION}.src.tar.xz" 33 | +CLANG_ARCHIVE="http://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang-${CLANG_VERSION}.src.tar.xz" 34 | +CRT_ARCHIVE="http://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/compiler-rt-${CLANG_VERSION}.src.tar.xz" 35 | +CTE_ARCHIVE="http://github.com/llvm/llvm-project/releases/download/llvmorg-${CLANG_VERSION}/clang-tools-extra-${CLANG_VERSION}.src.tar.xz" 36 | +CMAKE_ARCHIVE="http://cmake.org/files/v3.18/cmake-${CMAKE_VERSION}.tar.gz" 37 | +NASM_ARCHIVE="http://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.bz2" 38 | 39 | ALL_ARCHIVES="$GMP_ARCHIVE $MPFR_ARCHIVE $MPC_ARCHIVE \ 40 | $GCC_ARCHIVE $BINUTILS_ARCHIVE $GDB_ARCHIVE $IASL_ARCHIVE \ 41 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0001-soc-skylake-me.c-Print-status-regardless-of-device-e.patch: -------------------------------------------------------------------------------- 1 | From cf41f0aa19329802676feed24df1ba9697d065a1 Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Mon, 18 May 2020 14:02:27 -0500 4 | Subject: [PATCH 1/9] soc/skylake/me.c: Print status regardless of device 5 | enable state 6 | 7 | Checking the CSE device status before printing means it will skip 8 | printing for devices with the ME disabled, leaving the user no easy 9 | way to verify the ME is properly disabled. Remove the check. 10 | 11 | Test: build/boot Librem 13v4, verify ME status printed as expected 12 | on device with disabled/neutered ME. 13 | 14 | Signed-off-by: Matt DeVillier 15 | Change-Id: Iaa4f4a369d878a52136c3479027443ea4e731a36 16 | --- 17 | src/soc/intel/skylake/me.c | 3 --- 18 | 1 file changed, 3 deletions(-) 19 | 20 | diff --git a/src/soc/intel/skylake/me.c b/src/soc/intel/skylake/me.c 21 | index 89491f89c3..08aceb3f83 100644 22 | --- a/src/soc/intel/skylake/me.c 23 | +++ b/src/soc/intel/skylake/me.c 24 | @@ -188,9 +188,6 @@ void intel_me_status(void) 25 | union me_hfsts3 hfs3; 26 | union me_hfsts6 hfs6; 27 | 28 | - if (!is_cse_enabled()) 29 | - return; 30 | - 31 | hfs1.data = me_read_config32(PCI_ME_HFSTS1); 32 | hfs2.data = me_read_config32(PCI_ME_HFSTS2); 33 | hfs3.data = me_read_config32(PCI_ME_HFSTS3); 34 | -- 35 | 2.30.2 36 | 37 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0002-soc-cannonlake-me.c-Print-status-regardless-of-devic.patch: -------------------------------------------------------------------------------- 1 | From d7775b8a5a018930eece1ce9e50cb00863845d2e Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Fri, 19 Jun 2020 17:02:22 -0500 4 | Subject: [PATCH 2/9] soc/cannonlake/me.c: Print status regardless of device 5 | enable state 6 | 7 | Checking the CSE device status before printing means it will skip 8 | printing for devices with the ME disabled, leaving the user no easy 9 | way to verify the ME is properly disabled. Remove the check. 10 | 11 | Test: build/boot Librem Mini, verify ME status printed as expected 12 | on device with disabled/neutered ME. 13 | 14 | Change-Id: I939333199aa699039fec727beb094e4eb2ad7149 15 | Signed-off-by: Matt DeVillier 16 | --- 17 | src/soc/intel/cannonlake/me.c | 3 --- 18 | 1 file changed, 3 deletions(-) 19 | 20 | diff --git a/src/soc/intel/cannonlake/me.c b/src/soc/intel/cannonlake/me.c 21 | index 7bbe1ae730..4fe5a96ade 100644 22 | --- a/src/soc/intel/cannonlake/me.c 23 | +++ b/src/soc/intel/cannonlake/me.c 24 | @@ -103,9 +103,6 @@ void dump_me_status(void *unused) 25 | union me_hfsts5 hfsts5; 26 | union me_hfsts6 hfsts6; 27 | 28 | - if (!is_cse_enabled()) 29 | - return; 30 | - 31 | hfsts1.data = me_read_config32(PCI_ME_HFSTS1); 32 | hfsts2.data = me_read_config32(PCI_ME_HFSTS2); 33 | hfsts3.data = me_read_config32(PCI_ME_HFSTS3); 34 | -- 35 | 2.30.2 36 | 37 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0003-soc-intel-cannonlake-Add-PcieRpHotPlug-config-to-FSP.patch: -------------------------------------------------------------------------------- 1 | From cda3f1eb067e07e4a7110ef482912273d690be9e Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Tue, 25 Jan 2022 12:16:44 -0600 4 | Subject: [PATCH 5/9] soc/intel/cannonlake: Add PcieRpHotPlug config to FSP-M 5 | MIME-Version: 1.0 6 | Content-Type: text/plain; charset=UTF-8 7 | Content-Transfer-Encoding: 8bit 8 | 9 | Commit b67c5ed [3rdparty/fsp: Update submodule pointer to newest master] 10 | updated the FSP binaries/headers for Comet Lake, which included a change 11 | moving PcieRpHotPlug from FSP-S to FSP-M. Unfortunately the existing 12 | UDP in FSP-S was left in and deprecated, which allowed the change to go 13 | unnoticed until it was discovered that hotplug wasn't working. 14 | 15 | Since other related platforms (WHL, CFL) share the SoC code but use 16 | different FSP packages, add the setting of the PcieRpHotPlug UPD to 17 | romstage/FSP-M and guard it with '#if CONFIG(SOC_INTEL_COMETLAKE)'. 18 | 19 | Test: build/boot Purism Librem 14, verify WiFi killswitch operates 20 | as expected / WiFi is re-enabled when turning switch to on position. 21 | 22 | Change-Id: I4e1c2ea909933ab21921e63ddeb31cefe1ceef13 23 | Signed-off-by: Matt DeVillier 24 | Reviewed-on: https://review.coreboot.org/c/coreboot/+/61377 25 | Tested-by: build bot (Jenkins) 26 | Reviewed-by: Michael Niewöhner 27 | Reviewed-by: Paul Menzel 28 | Reviewed-by: Nico Huber 29 | --- 30 | src/soc/intel/cannonlake/romstage/fsp_params.c | 1 + 31 | 1 file changed, 1 insertion(+) 32 | 33 | diff --git a/src/soc/intel/cannonlake/romstage/fsp_params.c b/src/soc/intel/cannonlake/romstage/fsp_params.c 34 | index 8cb6c92a65..0b63bd52f9 100644 35 | --- a/src/soc/intel/cannonlake/romstage/fsp_params.c 36 | +++ b/src/soc/intel/cannonlake/romstage/fsp_params.c 37 | @@ -59,6 +59,7 @@ void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) 38 | m_cfg->EnableC6Dram = config->enable_c6dram; 39 | #if CONFIG(SOC_INTEL_COMETLAKE) 40 | m_cfg->SerialIoUartDebugControllerNumber = CONFIG_UART_FOR_CONSOLE; 41 | + memcpy(tconfig->PcieRpHotPlug, config->PcieRpHotPlug, sizeof(tconfig->PcieRpHotPlug)); 42 | #else 43 | m_cfg->PcdSerialIoUartNumber = CONFIG_UART_FOR_CONSOLE; 44 | #endif 45 | -- 46 | 2.30.2 47 | 48 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0004-soc-intel-skylake-move-heci_init-from-bootblock-to-r.patch: -------------------------------------------------------------------------------- 1 | From 6d4b0be203b99e66043991796e1fdbbba26ba3ce Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Tue, 25 Jan 2022 12:41:49 -0600 4 | Subject: [PATCH 6/9] soc/intel/skylake: move heci_init() from bootblock to 5 | romstage 6 | 7 | Aligns with all other soc/intel/common platforms calling heci_init(). 8 | 9 | Test: build/boot Purism Librem 13v2 10 | 11 | Change-Id: I43029426c5683077c111b3382cf4c8773b3e5b20 12 | Signed-off-by: Matt DeVillier 13 | Reviewed-on: https://review.coreboot.org/c/coreboot/+/61378 14 | Reviewed-by: Subrata Banik 15 | Reviewed-by: Angel Pons 16 | Tested-by: build bot (Jenkins) 17 | --- 18 | src/soc/intel/skylake/bootblock/pch.c | 4 ---- 19 | src/soc/intel/skylake/romstage/romstage.c | 3 +++ 20 | 2 files changed, 3 insertions(+), 4 deletions(-) 21 | 22 | diff --git a/src/soc/intel/skylake/bootblock/pch.c b/src/soc/intel/skylake/bootblock/pch.c 23 | index 1685e43e0e..ec60cabbea 100644 24 | --- a/src/soc/intel/skylake/bootblock/pch.c 25 | +++ b/src/soc/intel/skylake/bootblock/pch.c 26 | @@ -2,7 +2,6 @@ 27 | #include 28 | #include 29 | #include 30 | -#include 31 | #include 32 | #include 33 | #include 34 | @@ -141,8 +140,5 @@ void bootblock_pch_init(void) 35 | 36 | enable_rtc_upper_bank(); 37 | 38 | - /* initialize Heci interface */ 39 | - heci_init(HECI1_BASE_ADDRESS); 40 | - 41 | gspi_early_bar_init(); 42 | } 43 | diff --git a/src/soc/intel/skylake/romstage/romstage.c b/src/soc/intel/skylake/romstage/romstage.c 44 | index 30f65eae01..7e891b19f8 100644 45 | --- a/src/soc/intel/skylake/romstage/romstage.c 46 | +++ b/src/soc/intel/skylake/romstage/romstage.c 47 | @@ -4,6 +4,7 @@ 48 | #include 49 | #include 50 | #include 51 | +#include 52 | #include 53 | #include 54 | #include 55 | @@ -127,6 +128,8 @@ void mainboard_romstage_entry(void) 56 | systemagent_early_init(); 57 | /* Program SMBus base address and enable it */ 58 | smbus_common_init(); 59 | + /* initialize Heci interface */ 60 | + heci_init(HECI1_BASE_ADDRESS); 61 | ps = pmc_get_power_state(); 62 | s3wake = pmc_fill_power_state(ps) == ACPI_S3; 63 | fsp_memory_init(s3wake); 64 | -- 65 | 2.30.2 66 | 67 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0005-soc-intel-common-cse-Drop-CSE-library-usage-in-bootb.patch: -------------------------------------------------------------------------------- 1 | From 237477540b03e3066ce0ffe51310a06f91e89252 Mon Sep 17 00:00:00 2001 2 | From: Subrata Banik 3 | Date: Wed, 26 Jan 2022 01:42:18 +0530 4 | Subject: [PATCH 7/9] soc/intel/common/cse: Drop CSE library usage in bootblock 5 | 6 | This patch drops the CSE common code block from getting compiled 7 | in bootblock without any SoC code using heci communication so 8 | early in the boot flow. 9 | 10 | BUG=none 11 | TEST=Able to build brya, purism/librem_skl without any compilation issue. 12 | 13 | Signed-off-by: Subrata Banik 14 | Change-Id: Ib4d221c6f19b60aeaf64696e64d0c4209dbf14e7 15 | Reviewed-on: https://review.coreboot.org/c/coreboot/+/61382 16 | Tested-by: build bot (Jenkins) 17 | Reviewed-by: Tim Wawrzynczak 18 | Reviewed-by: EricR Lai 19 | Reviewed-by: Angel Pons 20 | Reviewed-by: Matt DeVillier 21 | --- 22 | src/soc/intel/common/block/cse/Makefile.inc | 1 - 23 | 1 file changed, 1 deletion(-) 24 | 25 | diff --git a/src/soc/intel/common/block/cse/Makefile.inc b/src/soc/intel/common/block/cse/Makefile.inc 26 | index eac7d90424..339ede11b8 100644 27 | --- a/src/soc/intel/common/block/cse/Makefile.inc 28 | +++ b/src/soc/intel/common/block/cse/Makefile.inc 29 | @@ -1,4 +1,3 @@ 30 | -bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c 31 | romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c 32 | ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_CSE) += cse.c 33 | romstage-$(CONFIG_SOC_INTEL_CSE_LITE_SKU) += cse_lite.c 34 | -- 35 | 2.30.2 36 | 37 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0006-soc-intel-common-cse-skip-heci_init-if-HECI1-is-disa.patch: -------------------------------------------------------------------------------- 1 | From 8d416eec8ba1d929b7afd4718161ae0c1c4e24e3 Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Tue, 25 Jan 2022 19:48:38 -0600 4 | Subject: [PATCH 8/9] soc/intel/common/cse: skip heci_init() if HECI1 is 5 | disabled 6 | 7 | If the HECI1 PCI device is disabled, either via devicetree or other 8 | method (HAP, me_cleaner), then we don't want/need to program a BAR, 9 | set the PCI config, or call heci_reset(), as the latter will result 10 | in a 15s timeout delay when booting. 11 | 12 | Test: build/boot Purism Librem 13v2, verify heci_reset() 13 | timeout delay is no longer present. 14 | 15 | Change-Id: I0babe417173d10e37327538dc9e7aae980225367 16 | Signed-off-by: Matt DeVillier 17 | --- 18 | src/soc/intel/common/block/cse/cse.c | 4 ++++ 19 | 1 file changed, 4 insertions(+) 20 | 21 | diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c 22 | index f37ff9589e..eb4597b82d 100644 23 | --- a/src/soc/intel/common/block/cse/cse.c 24 | +++ b/src/soc/intel/common/block/cse/cse.c 25 | @@ -91,6 +91,10 @@ void heci_init(uintptr_t tempbar) 26 | 27 | u16 pcireg; 28 | 29 | + /* Check if device enabled */ 30 | + if (!is_cse_enabled()) 31 | + return; 32 | + 33 | /* Assume it is already initialized, nothing else to do */ 34 | if (get_cse_bar(dev)) 35 | return; 36 | -- 37 | 2.30.2 38 | 39 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0007-mb-purism-librem_skl-disable-HECI-PCI-device.patch: -------------------------------------------------------------------------------- 1 | From 7e8b5f1b32f2d7b12ed3df191d3f4b1f1254489c Mon Sep 17 00:00:00 2001 2 | From: Matt DeVillier 3 | Date: Tue, 25 Jan 2022 19:52:44 -0600 4 | Subject: [PATCH 9/9] mb/purism/librem_skl: disable HECI PCI device 5 | 6 | As all librem_skl devices ship with the ME disabled via HAP bit and ME 7 | firmware "neutralized" via me_cleaner, the HECI1 PCI device should be 8 | marked off/disabled to ensure that heci_reset() is not called at the end 9 | of heci_init(), as this causes a 15s timeout delay when booting 10 | (introduced in commit cb2fd20 [soc/intel/common: Add HECI Reset flow in 11 | the CSE driver]). 12 | 13 | Change-Id: Ib6bfcfd97e32bb9cf5be33535d77eea8227a8f9f 14 | Signed-off-by: Matt DeVillier 15 | --- 16 | src/mainboard/purism/librem_skl/devicetree.cb | 2 +- 17 | 1 file changed, 1 insertion(+), 1 deletion(-) 18 | 19 | diff --git a/src/mainboard/purism/librem_skl/devicetree.cb b/src/mainboard/purism/librem_skl/devicetree.cb 20 | index 5efb1e2aed..68fa343b3c 100644 21 | --- a/src/mainboard/purism/librem_skl/devicetree.cb 22 | +++ b/src/mainboard/purism/librem_skl/devicetree.cb 23 | @@ -162,7 +162,7 @@ chip soc/intel/skylake 24 | device pci 14.1 on end # USB xDCI (OTG) 25 | device pci 14.2 on end # Thermal Subsystem 26 | device pci 14.3 off end # Camera 27 | - device pci 16.0 on end # Management Engine Interface 1 28 | + device pci 16.0 off end # Management Engine Interface 1 29 | device pci 16.1 off end # Management Engine Interface 2 30 | device pci 16.2 off end # Management Engine IDE-R 31 | device pci 16.3 off end # Management Engine KT Redirection 32 | -- 33 | 2.30.2 34 | 35 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0008-makefile-opt-libs.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive coreboot-4.15/src/arch/x86/Makefile.inc d0cfc7920dbe4059/src/arch/x86/Makefile.inc 2 | --- coreboot-4.15/src/arch/x86/Makefile.inc 2021-11-09 15:49:46.000000000 +0000 3 | +++ d0cfc7920dbe4059/src/arch/x86/Makefile.inc 2022-03-28 10:25:28.405176193 +0000 4 | @@ -63,7 +63,7 @@ 5 | 6 | $$(objcbfs)/$(1).debug: $$$$($(1)-libs) $$$$($(1)-objs) 7 | @printf " LINK $$(subst $$(obj)/,,$$(@))\n" 8 | - $$(LD_$(1)) $$(LDFLAGS_$(1)) -o $$@ -L$$(obj) $$(COMPILER_RT_FLAGS_$(1)) --whole-archive --start-group $$(filter-out %.ld,$$($(1)-objs)) $$($(1)-libs) --no-whole-archive $$(COMPILER_RT_$(1)) --end-group -T $(call src-to-obj,$(1),$(CONFIG_MEMLAYOUT_LD_FILE)) --oformat $(2) 9 | + $$(LD_$(1)) $$(LDFLAGS_$(1)) -o $$@ -L$$(obj) $$(COMPILER_RT_FLAGS_$(1)) --whole-archive --start-group $$(filter-out %.ld,$$($(1)-objs)) $$($(1)-libs) --no-whole-archive $$(COMPILER_RT_$(1)) --end-group -T $(call src-to-obj,$(1),$(CONFIG_MEMLAYOUT_LD_FILE)) --oformat $(2) $(OPT_LIBS) 10 | -LANG=C LC_ALL= $$(OBJCOPY_$(1)) --only-section .illegal_globals $$(@) $$(objcbfs)/$(1)_null.offenders >/dev/null 2>&1 11 | if [ -z "$$$$($$(NM_$(1)) $$(objcbfs)/$(1)_null.offenders 2>&1 | grep 'no symbols')" ];then \ 12 | echo "Forbidden global variables in $(1):"; \ 13 | @@ -208,7 +208,7 @@ 14 | 15 | $(objcbfs)/postcar.debug: $$(postcar-objs) 16 | @printf " LINK $(subst $(obj)/,,$(@))\n" 17 | - $(LD_postcar) $(LDFLAGS_postcar) -o $@ -L$(obj) $(COMPILER_RT_FLAGS_postcar) --whole-archive --start-group $(filter-out %.ld,$^) --no-whole-archive $(COMPILER_RT_postcar) --end-group -T $(call src-to-obj,postcar,$(CONFIG_MEMLAYOUT_LD_FILE)) 18 | + $(LD_postcar) $(LDFLAGS_postcar) -o $@ -L$(obj) $(COMPILER_RT_FLAGS_postcar) --whole-archive --start-group $(filter-out %.ld,$^) --no-whole-archive $(COMPILER_RT_postcar) --end-group -T $(call src-to-obj,postcar,$(CONFIG_MEMLAYOUT_LD_FILE)) $(OPT_LIBS) 19 | 20 | $(objcbfs)/postcar.elf: $(objcbfs)/postcar.debug.rmod 21 | cp $< $@ 22 | @@ -289,11 +289,11 @@ 23 | 24 | $(objcbfs)/ramstage.debug: $(objgenerated)/ramstage.o $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) 25 | @printf " CC $(subst $(obj)/,,$(@))\n" 26 | - $(LD_ramstage) $(CPPFLAGS) $(LDFLAGS_ramstage) -o $@ -L$(obj) $< -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) 27 | + $(LD_ramstage) $(CPPFLAGS) $(LDFLAGS_ramstage) -o $@ -L$(obj) $< -T $(call src-to-obj,ramstage,$(CONFIG_MEMLAYOUT_LD_FILE)) $(OPT_LIBS) 28 | 29 | $(objgenerated)/ramstage.o: $$(ramstage-objs) $(COMPILER_RT_ramstage) $$(ramstage-libs) 30 | @printf " CC $(subst $(obj)/,,$(@))\n" 31 | - $(LD_ramstage) $(LD_MACHINE) -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group 32 | + $(LD_ramstage) $(LD_MACHINE) -r -o $@ $(COMPILER_RT_FLAGS_ramstage) --whole-archive --start-group $(filter-out %.ld,$(ramstage-objs)) $(ramstage-libs) --no-whole-archive $(COMPILER_RT_ramstage) --end-group $(OPT_LIBS) 33 | 34 | endif # CONFIG_ARCH_RAMSTAGE_X86_32 / CONFIG_ARCH_RAMSTAGE_X86_64 35 | 36 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0009-rcba_pirq-printk.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive coreboot-4.15/src/southbridge/intel/common/rcba_pirq.c d0cfc7920dbe4059/src/southbridge/intel/common/rcba_pirq.c 2 | --- coreboot-4.15/src/southbridge/intel/common/rcba_pirq.c 2021-11-09 15:49:46.000000000 +0000 3 | +++ d0cfc7920dbe4059/src/southbridge/intel/common/rcba_pirq.c 2022-03-28 08:22:01.229011959 +0000 4 | @@ -85,7 +85,7 @@ 5 | pin_irq_map[map_count].apic_gsi = 16 + pirq_idx(pirq); 6 | printk(BIOS_SPEW, "ACPI_PIRQ_GEN: %s: pin=%d pirq=%ld\n", 7 | dev_path(dev), int_pin - PCI_INT_A, 8 | - pirq_idx(pin_irq_map[map_count].pic_pirq)); 9 | + (long) pirq_idx(pin_irq_map[map_count].pic_pirq)); 10 | map_count++; 11 | } 12 | 13 | -------------------------------------------------------------------------------- /patches/coreboot-4.15/0010-genbuild-iasl.patch: -------------------------------------------------------------------------------- 1 | --- ../../clean/coreboot-4.15/util/genbuild_h/genbuild_h.sh 2021-11-09 15:49:46.000000000 +0000 2 | +++ 18c82f9236843b47/util/genbuild_h/genbuild_h.sh 2022-04-01 09:53:41.944914614 +0000 3 | @@ -51,10 +51,12 @@ 4 | # Look for IASL in XGCCPATH and xcompile. Unfortunately, 5 | # xcompile isn't available on the first build. 6 | # If neither of those gives a valid iasl, check the path. 7 | -IASL="${XGCCPATH}iasl" 8 | -eval $(grep ^IASL:= "$XCOMPILE" 2>/dev/null | sed s,:=,=,) 9 | -if [ ! -x "${IASL}" ]; then 10 | - IASL=$(command -v iasl) 11 | +if [ -z "${IASL}" ]; then 12 | + IASL="${XGCCPATH}iasl" 13 | + eval $(grep ^IASL:= "$XCOMPILE" 2>/dev/null | sed s,:=,=,) 14 | + if [ ! -x "${IASL}" ]; then 15 | + IASL=$(command -v iasl) 16 | + fi 17 | fi 18 | IASLVERSION="$(${IASL} -v | grep version | sed 's/.*version //')" >/dev/null 19 | 20 | --- ../../clean/coreboot-4.15/util/xcompile/xcompile 2021-11-09 15:49:46.000000000 +0000 21 | +++ 67705c5ad4adc865/util/xcompile/xcompile 2022-04-01 12:08:27.348277736 +0000 22 | @@ -52,7 +52,9 @@ 23 | } 24 | 25 | 26 | -if [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 27 | +if [ -n "${IASL}" ]; then 28 | + true 29 | +elif [ "$("${XGCCPATH}/iasl" 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 30 | IASL=${XGCCPATH}/iasl 31 | elif [ "$(iasl 2>/dev/null | grep -c ACPI)" -gt 0 ]; then 32 | IASL=iasl 33 | -------------------------------------------------------------------------------- /patches/cryptsetup-1.7.3.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive ../../clean/cryptsetup-1.7.3/src/Makefile.in ./cryptsetup-1.7.3/src/Makefile.in 2 | --- ../../clean/cryptsetup-1.7.3/src/Makefile.in 2016-10-28 09:45:06.000000000 -0400 3 | +++ cryptsetup-1.7.3/src/Makefile.in 2017-01-27 17:24:13.115962328 -0500 4 | @@ -479,6 +479,8 @@ 5 | cryptsetup_LDADD = \ 6 | $(top_builddir)/lib/libcryptsetup.la \ 7 | @POPT_LIBS@ \ 8 | + @UUID_LIBS@ \ 9 | + @DEVMAPPER_LIBS@ \ 10 | @PWQUALITY_LIBS@ \ 11 | @PASSWDQC_LIBS@ 12 | 13 | @@ -503,6 +505,8 @@ 14 | 15 | @VERITYSETUP_TRUE@veritysetup_LDADD = \ 16 | @VERITYSETUP_TRUE@ $(top_builddir)/lib/libcryptsetup.la \ 17 | +@VERITYSETUP_TRUE@ @UUID_LIBS@ \ 18 | +@VERITYSETUP_TRUE@ @DEVMAPPER_LIBS@ \ 19 | @VERITYSETUP_TRUE@ @POPT_LIBS@ 20 | 21 | @VERITYSETUP_TRUE@veritysetup_CFLAGS = $(cryptsetup_CFLAGS) 22 | -------------------------------------------------------------------------------- /patches/dropbear-2016.74.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ../clean/dropbear-2016.74/svr-chansession.c ./dropbear-2016.74/svr-chansession.c 2 | --- ../clean/dropbear-2016.74/svr-chansession.c 2016-07-21 11:17:09.000000000 -0400 3 | +++ dropbear-2016.74/svr-chansession.c 2017-09-19 11:01:34.889121503 -0400 4 | @@ -925,10 +925,10 @@ 5 | if ((setgid(ses.authstate.pw_gid) < 0) || 6 | (initgroups(ses.authstate.pw_name, 7 | ses.authstate.pw_gid) < 0)) { 8 | - dropbear_exit("Error changing user group"); 9 | + //dropbear_exit("Error changing user group"); 10 | } 11 | if (setuid(ses.authstate.pw_uid) < 0) { 12 | - dropbear_exit("Error changing user"); 13 | + //dropbear_exit("Error changing user"); 14 | } 15 | } else { 16 | /* ... but if the daemon is the same uid as the requested uid, we don't 17 | -------------------------------------------------------------------------------- /patches/fbwhiptail.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive clean/Makefile 43944c0993ea92c8/Makefile 2 | --- clean/Makefile 2022-03-27 21:32:45.691722963 +0000 3 | +++ 43944c0993ea92c8/Makefile 2022-03-27 21:33:14.343558010 +0000 4 | @@ -12,7 +12,7 @@ 5 | 6 | 7 | fbwhiptail: fbwhiptail.c fbwhiptail_menu.c cairo_menu.c cairo_utils.c cairo_dri.c cairo_linuxfb.c 8 | - $(CC) -g -O0 -o $@ $^ -lm -lcairo -lpixman-1 -lpng16 -lz 9 | + $(CC) -g -O0 $(CFLAGS) -o $@ $^ -lm -lcairo -lpixman-1 -lpng16 -lz 10 | 11 | gtkwhiptail: fbwhiptail.c fbwhiptail_menu.c fbwhiptail_menu.h cairo_menu.c cairo_utils.c 12 | $(CC) -g -O0 -DGTKWHIPTAIL -o $@ $^ -lm \ 13 | -------------------------------------------------------------------------------- /patches/kexec-2.0.20-duplicate-symbols.patch: -------------------------------------------------------------------------------- 1 | From cc087b11462af9f971a2c090d07e8d780a867b50 Mon Sep 17 00:00:00 2001 2 | From: Kairui Song 3 | Date: Wed, 29 Jan 2020 13:38:19 +0800 4 | Subject: kexec-tools: Remove duplicated variable declarations 5 | 6 | When building kexec-tools for Fedora 32, following error is observed: 7 | 8 | /usr/bin/ld: kexec/arch/x86_64/kexec-bzImage64.o:(.bss+0x0): multiple definition of `bzImage_support_efi_boot'; 9 | kexec/arch/i386/kexec-bzImage.o:(.bss+0x0): first defined here 10 | 11 | /builddir/build/BUILD/kexec-tools-2.0.20/kexec/arch/arm/../../fs2dt.h:33: multiple definition of `my_debug'; 12 | kexec/fs2dt.o:/builddir/build/BUILD/kexec-tools-2.0.20/kexec/fs2dt.h:33: first defined here 13 | 14 | /builddir/build/BUILD/kexec-tools-2.0.20/kexec/arch/arm64/kexec-arm64.h:68: multiple definition of `arm64_mem'; 15 | kexec/fs2dt.o:/builddir/build/BUILD/kexec-tools-2.0.20/././kexec/arch/arm64/kexec-arm64.h:68: first defined here 16 | 17 | /builddir/build/BUILD/kexec-tools-2.0.20/kexec/arch/arm64/kexec-arm64.h:54: multiple definition of `initrd_size'; 18 | kexec/fs2dt.o:/builddir/build/BUILD/kexec-tools-2.0.20/././kexec/arch/arm64/kexec-arm64.h:54: first defined here 19 | 20 | /builddir/build/BUILD/kexec-tools-2.0.20/kexec/arch/arm64/kexec-arm64.h:53: multiple definition of `initrd_base'; 21 | kexec/fs2dt.o:/builddir/build/BUILD/kexec-tools-2.0.20/././kexec/arch/arm64/kexec-arm64.h:53: first defined here 22 | 23 | And apparently, these variables are wrongly declared multiple times. So 24 | remove duplicated declaration. 25 | 26 | Signed-off-by: Kairui Song 27 | Signed-off-by: Simon Horman 28 | --- 29 | kexec/arch/arm64/kexec-arm64.h | 6 +++--- 30 | kexec/arch/ppc64/kexec-elf-ppc64.c | 2 -- 31 | kexec/arch/x86_64/kexec-bzImage64.c | 1 - 32 | kexec/fs2dt.h | 2 +- 33 | 4 files changed, 4 insertions(+), 7 deletions(-) 34 | 35 | diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h 36 | index 628de79..ed447ac 100644 37 | --- a/kexec/arch/arm64/kexec-arm64.h 38 | +++ b/kexec/arch/arm64/kexec-arm64.h 39 | @@ -50,8 +50,8 @@ int zImage_arm64_load(int argc, char **argv, const char *kernel_buf, 40 | void zImage_arm64_usage(void); 41 | 42 | 43 | -off_t initrd_base; 44 | -off_t initrd_size; 45 | +extern off_t initrd_base; 46 | +extern off_t initrd_size; 47 | 48 | /** 49 | * struct arm64_mem - Memory layout info. 50 | @@ -65,7 +65,7 @@ struct arm64_mem { 51 | }; 52 | 53 | #define arm64_mem_ngv UINT64_MAX 54 | -struct arm64_mem arm64_mem; 55 | +extern struct arm64_mem arm64_mem; 56 | 57 | uint64_t get_phys_offset(void); 58 | uint64_t get_vp_offset(void); 59 | diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c 60 | index 3510b70..695b8b0 100644 61 | --- a/kexec/arch/ppc64/kexec-elf-ppc64.c 62 | +++ b/kexec/arch/ppc64/kexec-elf-ppc64.c 63 | @@ -44,8 +44,6 @@ 64 | uint64_t initrd_base, initrd_size; 65 | unsigned char reuse_initrd = 0; 66 | const char *ramdisk; 67 | -/* Used for enabling printing message from purgatory code */ 68 | -int my_debug = 0; 69 | 70 | int elf_ppc64_probe(const char *buf, off_t len) 71 | { 72 | diff --git a/kexec/arch/x86_64/kexec-bzImage64.c b/kexec/arch/x86_64/kexec-bzImage64.c 73 | index 8edb3e4..ba8dc48 100644 74 | --- a/kexec/arch/x86_64/kexec-bzImage64.c 75 | +++ b/kexec/arch/x86_64/kexec-bzImage64.c 76 | @@ -42,7 +42,6 @@ 77 | #include 78 | 79 | static const int probe_debug = 0; 80 | -int bzImage_support_efi_boot; 81 | 82 | int bzImage64_probe(const char *buf, off_t len) 83 | { 84 | diff --git a/kexec/fs2dt.h b/kexec/fs2dt.h 85 | index 7633273..fe24931 100644 86 | --- a/kexec/fs2dt.h 87 | +++ b/kexec/fs2dt.h 88 | @@ -30,7 +30,7 @@ extern struct bootblock bb[1]; 89 | 90 | /* Used for enabling printing message from purgatory code 91 | * Only has implemented for PPC64 */ 92 | -int my_debug; 93 | +extern int my_debug; 94 | extern int dt_no_old_root; 95 | 96 | void reserve(unsigned long long where, unsigned long long length); 97 | -- 98 | cgit 99 | 100 | -------------------------------------------------------------------------------- /patches/kexec-2.0.20.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Makefile.in b/Makefile.in 2 | index fb01134..bf1973e 100644 3 | --- a/Makefile.in 4 | +++ b/Makefile.in 5 | @@ -157,12 +157,12 @@ include $(srcdir)/kexec/Makefile 6 | 7 | # vmcore-dmesg (read dmesg from a vmcore) 8 | # 9 | -include $(srcdir)/vmcore-dmesg/Makefile 10 | +#include $(srcdir)/vmcore-dmesg/Makefile 11 | 12 | # 13 | # kexec_test (test program) 14 | # 15 | -include $(srcdir)/kexec_test/Makefile 16 | +#include $(srcdir)/kexec_test/Makefile 17 | 18 | SPEC=$(PACKAGE_NAME).spec 19 | GENERATED_SRCS:= $(SPEC) 20 | diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c 21 | index 057ee14..43e017a 100644 22 | --- a/kexec/arch/i386/x86-linux-setup.c 23 | +++ b/kexec/arch/i386/x86-linux-setup.c 24 | @@ -137,7 +137,8 @@ static int setup_linux_vesafb(struct x86_linux_param_header *real_mode) 25 | goto out; 26 | if (-1 == ioctl(fd, FBIOGET_VSCREENINFO, &var)) 27 | goto out; 28 | - if (0 == strcmp(fix.id, "VESA VGA")) { 29 | + if (0 == strcmp(fix.id, "VESA VGA") 30 | + || 0 == strcmp(fix.id, "inteldrmfb")) { 31 | /* VIDEO_TYPE_VLFB */ 32 | real_mode->orig_video_isVGA = 0x23; 33 | } else if (0 == strcmp(fix.id, "EFI VGA")) { 34 | diff --git a/kexec/kexec.c b/kexec/kexec.c 35 | index bc6ab3d..b82725b 100644 36 | --- a/kexec/kexec.c 37 | +++ b/kexec/kexec.c 38 | @@ -805,6 +805,27 @@ static int my_load(const char *type, int fileind, int argc, char **argv, 39 | if (sort_segments(&info) < 0) { 40 | return -1; 41 | } 42 | + 43 | +#if 1 44 | + // force segment 0 to have memsz == bufsz 45 | + // so that it won't overwrite EBDA 46 | + if (info.segment[0].mem == 0) 47 | + { 48 | + if (kexec_debug) 49 | + printf("hack ebda into segment 0!\n"); 50 | + 51 | + uint8_t * ebda = calloc(1, info.segment[0].memsz); 52 | + memcpy(ebda, info.segment[0].buf, info.segment[0].bufsz); 53 | + info.segment[0].bufsz = info.segment[0].memsz; 54 | + info.segment[0].buf = ebda; 55 | + 56 | + // install some default EBDA values that are off scale, 57 | + // which will force Xen to use the multiboot info 58 | + *(uint16_t*)(ebda + 0x40e) = 0xFFFF; // segment 59 | + *(uint16_t*)(ebda + 0x413) = 0xFFFF; // size 60 | + } 61 | +#endif 62 | + 63 | /* if purgatory is loaded update it */ 64 | update_purgatory(&info); 65 | if (entry) 66 | diff --git a/purgatory/Makefile b/purgatory/Makefile 67 | index 2dd6c47..2de8f07 100644 68 | --- a/purgatory/Makefile 69 | +++ b/purgatory/Makefile 70 | @@ -44,7 +44,6 @@ purgatory/sha256.o: $(srcdir)/util_lib/sha256.c 71 | mkdir -p $(@D) 72 | $(COMPILE.c) -o $@ $^ 73 | 74 | -$(PURGATORY): CC=$(TARGET_CC) 75 | $(PURGATORY): CFLAGS=$(PURGATORY_EXTRA_CFLAGS) \ 76 | $($(ARCH)_PURGATORY_EXTRA_CFLAGS) \ 77 | -Os -fno-builtin -ffreestanding \ 78 | diff --git a/util/Makefile b/util/Makefile 79 | index 948ee63..833a897 100644 80 | --- a/util/Makefile 81 | +++ b/util/Makefile 82 | @@ -2,7 +2,7 @@ BIN_TO_HEX:= bin/bin-to-hex 83 | 84 | $(BIN_TO_HEX): $(srcdir)/util/bin-to-hex.c 85 | @$(MKDIR) -p $(@D) 86 | - $(LINK.o) $(CFLAGS) -o $@ $^ 87 | + $(BUILD_CC) $(BUILD_CFLAGS) -o $@ $^ 88 | 89 | $(BIN_TO_HEX): CC=$(BUILD_CC) 90 | $(BIN_TO_HEX): CFLAGS=$(BUILD_CFLAGS) 91 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0000-efi_bds.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive ../../clean/linux-4.14.62/arch/x86/boot/compressed/eboot.c linux-4.14.62/arch/x86/boot/compressed/eboot.c 2 | --- ../../clean/linux-4.14.62/arch/x86/boot/compressed/eboot.c 2018-08-09 06:16:40.000000000 -0400 3 | +++ linux-4.14.62/arch/x86/boot/compressed/eboot.c 2018-08-09 10:13:11.801000000 -0400 4 | @@ -630,8 +630,8 @@ 5 | u16 *s2; 6 | u8 *s1; 7 | int i; 8 | - unsigned long ramdisk_addr; 9 | - unsigned long ramdisk_size; 10 | + unsigned long ramdisk_addr = 0; 11 | + unsigned long ramdisk_size = 0; 12 | 13 | efi_early = c; 14 | sys_table = (efi_system_table_t *)(unsigned long)efi_early->table; 15 | @@ -686,9 +686,6 @@ 16 | /* Fill in upper bits of command line address, NOP on 32 bit */ 17 | boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32; 18 | 19 | - hdr->ramdisk_image = 0; 20 | - hdr->ramdisk_size = 0; 21 | - 22 | /* Clear APM BIOS info */ 23 | memset(bi, 0, sizeof(*bi)); 24 | 25 | @@ -712,10 +709,16 @@ 26 | 27 | if (status != EFI_SUCCESS) 28 | goto fail2; 29 | - hdr->ramdisk_image = ramdisk_addr & 0xffffffff; 30 | - hdr->ramdisk_size = ramdisk_size & 0xffffffff; 31 | - boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; 32 | - boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; 33 | + 34 | + // don't overwrite the bzImage or loader provided ramdisk pointer 35 | + // unless the kernel command line specified a different one. 36 | + if (ramdisk_addr != 0) 37 | + { 38 | + hdr->ramdisk_image = ramdisk_addr & 0xffffffff; 39 | + hdr->ramdisk_size = ramdisk_size & 0xffffffff; 40 | + boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32; 41 | + boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32; 42 | + } 43 | 44 | return boot_params; 45 | fail2: 46 | --- clean/linux-4.14.62/arch/x86/boot/compressed/early_serial_console.c 2018-08-09 12:16:40.000000000 +0200 47 | +++ linux-4.14.62/arch/x86/boot/compressed/early_serial_console.c 2018-09-28 11:59:36.824015244 +0200 48 | @@ -1,5 +1,5 @@ 49 | #include "misc.h" 50 | 51 | -int early_serial_base; 52 | +int early_serial_base = 0x3f8; 53 | 54 | #include "../early_serial_console.c" 55 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0001-fake-acpi.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ./clean/linux-4.9.80/drivers/acpi/acpica/evxfevnt.c linux-4.9.80/drivers/acpi/acpica/evxfevnt.c 2 | --- ./clean/linux-4.9.80/drivers/acpi/acpica/evxfevnt.c 2018-02-03 11:05:43.000000000 -0500 3 | +++ linux-4.9.80/drivers/acpi/acpica/evxfevnt.c 2018-02-07 15:51:28.786502597 -0500 4 | @@ -111,6 +111,8 @@ 5 | } 6 | 7 | ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode")); 8 | +printk("%s:%d faking ACPI mode\n", __func__, __LINE__); 9 | + return_ACPI_STATUS(AE_OK); 10 | return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); 11 | } 12 | 13 | diff --recursive -u ./clean/linux-4.9.80/drivers/acpi/acpica/hwacpi.c linux-4.9.80/drivers/acpi/acpica/hwacpi.c 14 | --- ./clean/linux-4.9.80/drivers/acpi/acpica/hwacpi.c 2018-02-03 11:05:43.000000000 -0500 15 | +++ linux-4.9.80/drivers/acpi/acpica/hwacpi.c 2018-02-07 15:51:35.126557868 -0500 16 | @@ -168,12 +168,16 @@ 17 | 18 | status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); 19 | if (ACPI_FAILURE(status)) { 20 | +printk("%s:%d faking ACPI mode\n", __func__, __LINE__); 21 | + return_UINT32(ACPI_SYS_MODE_ACPI); 22 | return_UINT32(ACPI_SYS_MODE_LEGACY); 23 | } 24 | 25 | if (value) { 26 | return_UINT32(ACPI_SYS_MODE_ACPI); 27 | } else { 28 | +//printk("%s:%d faking ACPI mode\n", __func__, __LINE__); 29 | +// return_UINT32(ACPI_SYS_MODE_ACPI); 30 | return_UINT32(ACPI_SYS_MODE_LEGACY); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0002-nmi-squelch.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ./clean/linux-4.9.80/arch/x86/kernel/nmi.c linux-4.9.80/arch/x86/kernel/nmi.c 2 | --- ./clean/linux-4.9.80/arch/x86/kernel/nmi.c 2018-02-03 11:05:43.000000000 -0500 3 | +++ linux-4.9.80/arch/x86/kernel/nmi.c 2018-02-07 18:56:10.475613884 -0500 4 | @@ -303,6 +303,8 @@ 5 | 6 | __this_cpu_add(nmi_stats.unknown, 1); 7 | 8 | +#if 0 9 | +// qemu generates these for some reason 10 | pr_emerg("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", 11 | reason, smp_processor_id()); 12 | 13 | @@ -311,6 +313,7 @@ 14 | nmi_panic(regs, "NMI: Not continuing"); 15 | 16 | pr_emerg("Dazed and confused, but trying to continue\n"); 17 | +#endif 18 | } 19 | NOKPROBE_SYMBOL(unknown_nmi_error); 20 | 21 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0003-fake-trampoline.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ./clean/linux-4.9.80/arch/x86/realmode/init.c linux-4.9.80/arch/x86/realmode/init.c 2 | --- ./clean/linux-4.9.80/arch/x86/realmode/init.c 2018-02-03 11:05:43.000000000 -0500 3 | +++ linux-4.9.80/arch/x86/realmode/init.c 2018-02-07 15:51:28.538500435 -0500 4 | @@ -35,8 +35,8 @@ 5 | /* Has to be under 1M so we can execute real-mode AP code. */ 6 | mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE); 7 | if (!mem) { 8 | - pr_info("No sub-1M memory is available for the trampoline\n"); 9 | - return; 10 | + mem = 0x4000; 11 | + pr_info("No sub-1M memory is available for the trampoline, guessing %p\n", mem); 12 | } 13 | 14 | memblock_reserve(mem, size); 15 | @@ -138,7 +138,12 @@ 16 | static int __init init_real_mode(void) 17 | { 18 | if (!real_mode_header) 19 | - panic("Real mode trampoline was not allocated"); 20 | + { 21 | + // ignore for now 22 | + //panic("Real mode trampoline was not allocated"); 23 | + pr_warn("Real mode trampoline was not allocated"); 24 | + return 0; 25 | + } 26 | 27 | setup_real_mode(); 28 | set_real_mode_permissions(); 29 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0010-winterfell-ahci.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ./clean/linux-4.9.80/drivers/ata/libahci.c linux-4.9.80/drivers/ata/libahci.c 2 | --- ./clean/linux-4.9.80/drivers/ata/libahci.c 2018-02-03 11:05:43.000000000 -0500 3 | +++ linux-4.9.80/drivers/ata/libahci.c 2018-02-07 18:02:32.526535910 -0500 4 | @@ -537,8 +537,12 @@ 5 | } 6 | 7 | /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ 8 | - if (!port_map && vers < 0x10300) { 9 | - port_map = (1 << ahci_nr_ports(cap)) - 1; 10 | + if (!port_map) { // && vers < 0x10300) { 11 | + printk("%s: saved_port=%02x\n", __func__, hpriv->saved_port_map); 12 | + writel(0x1, mmio + HOST_PORTS_IMPL); 13 | + port_map = readl(mmio + HOST_PORTS_IMPL); 14 | + 15 | + //port_map = (1 << ahci_nr_ports(cap)) - 1; 16 | dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map); 17 | 18 | /* write the fixed up value to the PI register */ 19 | -------------------------------------------------------------------------------- /patches/linux-4.14.62/0020-missing-symboltable.patch: -------------------------------------------------------------------------------- 1 | Thanks to a recent binutils change which doesn't generate unused 2 | symbols, it's now possible for thunk_64.o be completely empty with 3 | CONFIG_PREEMPTION: no text, no data, no symbols. 4 | 5 | We could edit the Makefile to only build that file when 6 | CONFIG_PREEMPTION is enabled, but that will likely create confusion 7 | if/when the thunks end up getting used by some other code again. 8 | 9 | Just ignore it and move on. 10 | 11 | Reported-by: Nathan Chancellor 12 | Signed-off-by: Josh Poimboeuf 13 | --- 14 | tools/objtool/elf.c | 7 +++++-- 15 | 1 file changed, 5 insertions(+), 2 deletions(-) 16 | 17 | diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c 18 | index be89c741ba9a..2b0f4f52f7b5 100644 19 | --- a/tools/objtool/elf.c 20 | +++ b/tools/objtool/elf.c 21 | @@ -380,8 +380,11 @@ static int read_symbols(struct elf *elf) 22 | 23 | symtab = find_section_by_name(elf, ".symtab"); 24 | if (!symtab) { 25 | - WARN("missing symbol table"); 26 | - return -1; 27 | + /* 28 | + * A missing symbol table is actually possible if it's an empty 29 | + * .o file. This can happen for thunk_64.o. 30 | + */ 31 | + return 0; 32 | } 33 | 34 | symtab_shndx = find_section_by_name(elf, ".symtab_shndx"); 35 | -- 36 | 2.29.2 37 | -------------------------------------------------------------------------------- /patches/lvm2-2.02.168/0010-misc.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u clean/LVM2.2.02.168/lib/mm/memlock.c lvm2.2.02.168/lib/mm/memlock.c 2 | --- clean/LVM2.2.02.168/lib/mm/memlock.c 2016-12-01 00:17:29.000000000 +0100 3 | +++ lvm2.2.02.168/lib/mm/memlock.c 2020-01-09 13:23:14.017310025 +0100 4 | @@ -150,6 +150,7 @@ 5 | 6 | static void _allocate_memory(void) 7 | { 8 | +#if 0 9 | #ifndef VALGRIND_POOL 10 | void *stack_mem; 11 | struct rlimit limit; 12 | @@ -208,11 +209,14 @@ 13 | for (i = 0; i < area; ++i) 14 | free(areas[i]); 15 | #endif 16 | +#endif 17 | } 18 | 19 | static void _release_memory(void) 20 | { 21 | +#if 0 22 | free(_malloc_mem); 23 | +#endif 24 | } 25 | 26 | /* 27 | @@ -288,7 +292,7 @@ 28 | 29 | if (lock == LVM_MLOCK) { 30 | if (mlock((const void*)from, sz) < 0) { 31 | - log_sys_error("mlock", line); 32 | + //log_sys_error("mlock", line); 33 | return 0; 34 | } 35 | } else { 36 | diff --recursive -u clean/LVM2.2.02.168/libdm/libdm-stats.c lvm2.2.02.168/libdm/libdm-stats.c 37 | --- clean/LVM2.2.02.168/libdm/libdm-stats.c 2016-12-01 00:17:30.000000000 +0100 38 | +++ lvm2.2.02.168/libdm/libdm-stats.c 2020-01-09 13:23:14.017310025 +0100 39 | @@ -17,7 +17,24 @@ 40 | 41 | #include "dmlib.h" 42 | 43 | +#if 0 44 | #include "math.h" /* log10() */ 45 | +#else 46 | +static int ilog10(double x) 47 | +{ 48 | + int e = 0; 49 | + 50 | + while(x > 10) 51 | + { 52 | + e++; 53 | + x = x / 10; 54 | + } 55 | + 56 | + return e; 57 | +} 58 | +#endif 59 | + 60 | + 61 | 62 | #include 63 | #include 64 | @@ -502,7 +519,11 @@ 65 | while(entry >= bins) { 66 | value = (double) (entry--)->upper; 67 | /* Use lround to avoid size_t -> double cast warning. */ 68 | +#if 0 69 | hist_len += 1 + (size_t) lround(log10(value / scale)); 70 | +#else 71 | + hist_len += 1 + ilog10(value / scale); 72 | +#endif 73 | if (entry != bins) 74 | hist_len++; /* ',' */ 75 | } 76 | @@ -1746,7 +1767,11 @@ 77 | } 78 | 79 | /* length of region_id or range start in characters */ 80 | +#if 0 81 | id_len = (i) ? 1 + (size_t) log10(i) : 1; 82 | +#else 83 | + id_len = (i) ? 1 + ilog10(i) : 1; 84 | +#endif 85 | buflen += id_len; 86 | j = i; 87 | do 88 | @@ -1761,7 +1786,11 @@ 89 | /* handle range */ 90 | if (i != j) { 91 | /* j is always > i, which is always >= 0 */ 92 | +#if 0 93 | id_len = 1 + (size_t) log10(j); 94 | +#else 95 | + id_len = 1 + ilog10(j); 96 | +#endif 97 | buflen += id_len + 1; /* range end plus "-" */ 98 | } 99 | buflen++; 100 | diff --recursive -u clean/LVM2.2.02.168/libdm/Makefile.in lvm2.2.02.168/libdm/Makefile.in 101 | --- clean/LVM2.2.02.168/libdm/Makefile.in 2016-12-01 00:17:30.000000000 +0100 102 | +++ lvm2.2.02.168/libdm/Makefile.in 2020-01-09 13:23:14.017310025 +0100 103 | @@ -56,7 +56,8 @@ 104 | 105 | CFLAGS += $(UDEV_CFLAGS) $(VALGRIND_CFLAGS) 106 | 107 | -LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS) 108 | +#LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS) 109 | +LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) 110 | 111 | device-mapper: all 112 | 113 | diff --recursive -u clean/LVM2.2.02.168/make.tmpl.in lvm2.2.02.168/make.tmpl.in 114 | --- clean/LVM2.2.02.168/make.tmpl.in 2016-12-01 00:17:30.000000000 +0100 115 | +++ lvm2.2.02.168/make.tmpl.in 2020-01-09 13:23:14.017310025 +0100 116 | @@ -142,7 +142,7 @@ 117 | M_INSTALL_PROGRAM = -m 555 118 | M_INSTALL_DATA = -m 444 119 | endif 120 | -INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP) 121 | +INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP_ARG) 122 | INSTALL_DATA = $(INSTALL) -p $(M_INSTALL_DATA) 123 | INSTALL_WDATA = $(INSTALL) -p -m 644 124 | 125 | @@ -260,8 +260,8 @@ 126 | #CFLAGS += -pg 127 | #LDFLAGS += -pg 128 | 129 | -STRIP= 130 | -#STRIP = -s 131 | +STRIP_ARG= 132 | +#STRIP_ARG = -s 133 | 134 | LVM_VERSION := $(shell cat $(top_srcdir)/VERSION) 135 | 136 | @@ -495,7 +495,7 @@ 137 | set -e; \ 138 | ( cat $(srcdir)/.exported_symbols; \ 139 | if test -n "$(EXPORTED_HEADER)"; then \ 140 | - $(CC) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \ 141 | + $(CC) $(CFLAGS) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \ 142 | $(SED) -ne "/^typedef|}/!s/.*[ *]\($(EXPORTED_FN_PREFIX)_[a-z0-9_]*\)(.*/\1/p"; \ 143 | fi \ 144 | ) > $@ 145 | diff --recursive -u clean/LVM2.2.02.168/tools/lvmcmdline.c lvm2.2.02.168/tools/lvmcmdline.c 146 | --- clean/LVM2.2.02.168/tools/lvmcmdline.c 2016-12-01 00:17:32.000000000 +0100 147 | +++ lvm2.2.02.168/tools/lvmcmdline.c 2020-01-09 13:23:49.057418263 +0100 148 | @@ -1817,6 +1817,7 @@ 149 | { 150 | int err = is_valid_fd(STDERR_FILENO); 151 | 152 | +#if 0 153 | if (!is_valid_fd(STDIN_FILENO) && 154 | !(stdin = fopen(_PATH_DEVNULL, "r"))) { 155 | if (err) 156 | @@ -1841,6 +1842,7 @@ 157 | strerror(errno)); 158 | return 0; 159 | } 160 | +#endif 161 | 162 | return 1; 163 | } 164 | @@ -2023,7 +2025,7 @@ 165 | */ 166 | dm_set_name_mangling_mode(DM_STRING_MANGLING_NONE); 167 | 168 | - if (!(cmd = create_toolcontext(0, NULL, 1, 0, 169 | + if (!(cmd = create_toolcontext(0, NULL, 0, 0, 170 | set_connections, set_filters))) { 171 | udev_fin_library_context(); 172 | return_NULL; 173 | -------------------------------------------------------------------------------- /patches/lvm2-2.02.168/0020-sort-wildcard.patch: -------------------------------------------------------------------------------- 1 | Only in 23a3d1cddd41b3ef: .patched 2 | Only in 23a3d1cddd41b3ef: .unpacked 3 | diff -u --recursive ../../clean/LVM2.2.02.168/lib/mm/memlock.c 23a3d1cddd41b3ef/lib/mm/memlock.c 4 | --- ../../clean/LVM2.2.02.168/lib/mm/memlock.c 2016-11-30 23:17:29.000000000 +0000 5 | +++ 23a3d1cddd41b3ef/lib/mm/memlock.c 2022-04-08 13:31:44.304786466 +0000 6 | @@ -150,6 +150,7 @@ 7 | 8 | static void _allocate_memory(void) 9 | { 10 | +#if 0 11 | #ifndef VALGRIND_POOL 12 | void *stack_mem; 13 | struct rlimit limit; 14 | @@ -208,11 +209,14 @@ 15 | for (i = 0; i < area; ++i) 16 | free(areas[i]); 17 | #endif 18 | +#endif 19 | } 20 | 21 | static void _release_memory(void) 22 | { 23 | +#if 0 24 | free(_malloc_mem); 25 | +#endif 26 | } 27 | 28 | /* 29 | @@ -288,7 +292,7 @@ 30 | 31 | if (lock == LVM_MLOCK) { 32 | if (mlock((const void*)from, sz) < 0) { 33 | - log_sys_error("mlock", line); 34 | + //log_sys_error("mlock", line); 35 | return 0; 36 | } 37 | } else { 38 | diff -u --recursive ../../clean/LVM2.2.02.168/libdm/Makefile.in 23a3d1cddd41b3ef/libdm/Makefile.in 39 | --- ../../clean/LVM2.2.02.168/libdm/Makefile.in 2016-11-30 23:17:30.000000000 +0000 40 | +++ 23a3d1cddd41b3ef/libdm/Makefile.in 2022-04-08 13:31:44.304786466 +0000 41 | @@ -56,7 +56,8 @@ 42 | 43 | CFLAGS += $(UDEV_CFLAGS) $(VALGRIND_CFLAGS) 44 | 45 | -LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS) 46 | +#LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) $(PTHREAD_LIBS) $(M_LIBS) 47 | +LIBS += $(SELINUX_LIBS) $(UDEV_LIBS) 48 | 49 | device-mapper: all 50 | 51 | diff -u --recursive ../../clean/LVM2.2.02.168/libdm/libdm-stats.c 23a3d1cddd41b3ef/libdm/libdm-stats.c 52 | --- ../../clean/LVM2.2.02.168/libdm/libdm-stats.c 2016-11-30 23:17:30.000000000 +0000 53 | +++ 23a3d1cddd41b3ef/libdm/libdm-stats.c 2022-04-08 13:31:44.304786466 +0000 54 | @@ -17,7 +17,24 @@ 55 | 56 | #include "dmlib.h" 57 | 58 | +#if 0 59 | #include "math.h" /* log10() */ 60 | +#else 61 | +static int ilog10(double x) 62 | +{ 63 | + int e = 0; 64 | + 65 | + while(x > 10) 66 | + { 67 | + e++; 68 | + x = x / 10; 69 | + } 70 | + 71 | + return e; 72 | +} 73 | +#endif 74 | + 75 | + 76 | 77 | #include 78 | #include 79 | @@ -502,7 +519,11 @@ 80 | while(entry >= bins) { 81 | value = (double) (entry--)->upper; 82 | /* Use lround to avoid size_t -> double cast warning. */ 83 | +#if 0 84 | hist_len += 1 + (size_t) lround(log10(value / scale)); 85 | +#else 86 | + hist_len += 1 + ilog10(value / scale); 87 | +#endif 88 | if (entry != bins) 89 | hist_len++; /* ',' */ 90 | } 91 | @@ -1746,7 +1767,11 @@ 92 | } 93 | 94 | /* length of region_id or range start in characters */ 95 | +#if 0 96 | id_len = (i) ? 1 + (size_t) log10(i) : 1; 97 | +#else 98 | + id_len = (i) ? 1 + ilog10(i) : 1; 99 | +#endif 100 | buflen += id_len; 101 | j = i; 102 | do 103 | @@ -1761,7 +1786,11 @@ 104 | /* handle range */ 105 | if (i != j) { 106 | /* j is always > i, which is always >= 0 */ 107 | +#if 0 108 | id_len = 1 + (size_t) log10(j); 109 | +#else 110 | + id_len = 1 + ilog10(j); 111 | +#endif 112 | buflen += id_len + 1; /* range end plus "-" */ 113 | } 114 | buflen++; 115 | diff -u --recursive ../../clean/LVM2.2.02.168/make.tmpl.in 23a3d1cddd41b3ef/make.tmpl.in 116 | --- ../../clean/LVM2.2.02.168/make.tmpl.in 2016-11-30 23:17:30.000000000 +0000 117 | +++ 23a3d1cddd41b3ef/make.tmpl.in 2022-04-08 18:34:46.622161263 +0000 118 | @@ -142,7 +142,7 @@ 119 | M_INSTALL_PROGRAM = -m 555 120 | M_INSTALL_DATA = -m 444 121 | endif 122 | -INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP) 123 | +INSTALL_PROGRAM = $(INSTALL) $(M_INSTALL_PROGRAM) $(STRIP_ARG) 124 | INSTALL_DATA = $(INSTALL) -p $(M_INSTALL_DATA) 125 | INSTALL_WDATA = $(INSTALL) -p -m 644 126 | 127 | @@ -260,8 +260,8 @@ 128 | #CFLAGS += -pg 129 | #LDFLAGS += -pg 130 | 131 | -STRIP= 132 | -#STRIP = -s 133 | +STRIP_ARG= 134 | +#STRIP_ARG = -s 135 | 136 | LVM_VERSION := $(shell cat $(top_srcdir)/VERSION) 137 | 138 | @@ -495,13 +495,13 @@ 139 | set -e; \ 140 | ( cat $(srcdir)/.exported_symbols; \ 141 | if test -n "$(EXPORTED_HEADER)"; then \ 142 | - $(CC) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \ 143 | + $(CC) $(CFLAGS) -E -P $(INCLUDES) $(DEFS) $(EXPORTED_HEADER) | \ 144 | $(SED) -ne "/^typedef|}/!s/.*[ *]\($(EXPORTED_FN_PREFIX)_[a-z0-9_]*\)(.*/\1/p"; \ 145 | fi \ 146 | ) > $@ 147 | 148 | EXPORTED_UC := $(shell echo $(EXPORTED_FN_PREFIX) | tr '[a-z]' '[A-Z]') 149 | -EXPORTED_SYMBOLS := $(wildcard $(srcdir)/.exported_symbols.Base $(srcdir)/.exported_symbols.$(EXPORTED_UC)_[0-9_]*[0-9]) 150 | +EXPORTED_SYMBOLS := $(sort $(wildcard $(srcdir)/.exported_symbols.Base $(srcdir)/.exported_symbols.$(EXPORTED_UC)_[0-9_]*[0-9])) 151 | 152 | .export.sym: .exported_symbols_generated $(EXPORTED_SYMBOLS) 153 | ifeq (,$(firstword $(EXPORTED_SYMBOLS))) 154 | diff -u --recursive ../../clean/LVM2.2.02.168/tools/lvmcmdline.c 23a3d1cddd41b3ef/tools/lvmcmdline.c 155 | --- ../../clean/LVM2.2.02.168/tools/lvmcmdline.c 2016-11-30 23:17:32.000000000 +0000 156 | +++ 23a3d1cddd41b3ef/tools/lvmcmdline.c 2022-04-08 13:31:44.304786466 +0000 157 | @@ -1817,6 +1817,7 @@ 158 | { 159 | int err = is_valid_fd(STDERR_FILENO); 160 | 161 | +#if 0 162 | if (!is_valid_fd(STDIN_FILENO) && 163 | !(stdin = fopen(_PATH_DEVNULL, "r"))) { 164 | if (err) 165 | @@ -1841,6 +1842,7 @@ 166 | strerror(errno)); 167 | return 0; 168 | } 169 | +#endif 170 | 171 | return 1; 172 | } 173 | @@ -2023,7 +2025,7 @@ 174 | */ 175 | dm_set_name_mangling_mode(DM_STRING_MANGLING_NONE); 176 | 177 | - if (!(cmd = create_toolcontext(0, NULL, 1, 0, 178 | + if (!(cmd = create_toolcontext(0, NULL, 0, 0, 179 | set_connections, set_filters))) { 180 | udev_fin_library_context(); 181 | return_NULL; 182 | -------------------------------------------------------------------------------- /patches/musl-1.2.2/0010-fastmath.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive ../../clean/musl-1.2.2/configure musl-1.2.2/configure 2 | --- ../../clean/musl-1.2.2/configure 2021-01-15 02:26:00.000000000 +0000 3 | +++ musl-1.2.2/configure 2022-03-25 16:39:28.415422944 +0000 4 | @@ -758,7 +758,7 @@ 5 | # 6 | if trycppif "__FAST_MATH__" \ 7 | "$CFLAGS_C99FSE $CPPFLAGS $CFLAGS" ; then 8 | -fail "$0: error: compiler has broken floating point; check CFLAGS" 9 | +echo "$0: error: compiler has broken floating point; check CFLAGS" 10 | fi 11 | 12 | printf "creating config.mak... " 13 | 14 | -------------------------------------------------------------------------------- /patches/musl-1.2.2/0020-relative-paths.patch: -------------------------------------------------------------------------------- 1 | diff --recursive -u ../../clean/musl-1.2.2/Makefile 9b969322012d796d/Makefile 2 | --- ../../clean/musl-1.2.2/Makefile 2021-01-15 02:26:00.000000000 +0000 3 | +++ 9b969322012d796d/Makefile 2022-04-06 08:59:03.691511448 +0000 4 | @@ -181,7 +181,7 @@ 5 | sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@ 6 | 7 | obj/musl-gcc: config.mak 8 | - printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@ 9 | + printf '#!/bin/sh\nMUSL_TOP="`dirname "$$0"`/.." ; export MUSL_TOP\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "$$MUSL_TOP%s/musl-gcc.specs"\n' "$(libdir)" > $@ 10 | chmod +x $@ 11 | 12 | obj/%-clang: $(srcdir)/tools/%-clang.in config.mak 13 | diff --recursive -u ../../clean/musl-1.2.2/tools/musl-gcc.specs.sh 9b969322012d796d/tools/musl-gcc.specs.sh 14 | --- ../../clean/musl-1.2.2/tools/musl-gcc.specs.sh 2021-01-15 02:26:00.000000000 +0000 15 | +++ 9b969322012d796d/tools/musl-gcc.specs.sh 2022-04-06 09:01:25.790800915 +0000 16 | @@ -5,22 +5,22 @@ 17 | %rename cpp_options old_cpp_options 18 | 19 | *cpp_options: 20 | --nostdinc -isystem $incdir -isystem include%s %(old_cpp_options) 21 | +-nostdinc -isystem %:getenv(MUSL_TOP $incdir) -isystem include%s %(old_cpp_options) 22 | 23 | *cc1: 24 | -%(cc1_cpu) -nostdinc -isystem $incdir -isystem include%s 25 | +%(cc1_cpu) -nostdinc -isystem %:getenv(MUSL_TOP $incdir) -isystem include%s 26 | 27 | *link_libgcc: 28 | --L$libdir -L .%s 29 | +-L%:getenv(MUSL_TOP $libdir) -L .%s 30 | 31 | *libgcc: 32 | libgcc.a%s %:if-exists(libgcc_eh.a%s) 33 | 34 | *startfile: 35 | -%{!shared: $libdir/Scrt1.o} $libdir/crti.o crtbeginS.o%s 36 | +%{!shared: %:getenv(MUSL_TOP $libdir/Scrt1.o)} %:getenv(MUSL_TOP $libdir/crti.o) crtbeginS.o%s 37 | 38 | *endfile: 39 | -crtendS.o%s $libdir/crtn.o 40 | +crtendS.o%s %:getenv(MUSL_TOP $libdir/crtn.o) 41 | 42 | *link: 43 | -dynamic-linker $ldso -nostdlib %{shared:-shared} %{static:-static} %{rdynamic:-export-dynamic} 44 | -------------------------------------------------------------------------------- /patches/pciutils-3.5.4.patch: -------------------------------------------------------------------------------- 1 | diff -u --recursive clean/pciutils-3.5.4/lib/types.h pciutils-3.5.4/lib/types.h 2 | --- clean/pciutils-3.5.4/lib/types.h 2017-02-24 15:22:04.000000000 -0500 3 | +++ pciutils-3.5.4/lib/types.h 2018-03-02 09:31:29.115000000 -0500 4 | @@ -8,6 +8,8 @@ 5 | 6 | #include 7 | 8 | +#define PCI_HAVE_STDINT_H 9 | + 10 | #ifndef PCI_HAVE_Uxx_TYPES 11 | 12 | #ifdef PCI_OS_WINDOWS 13 | -------------------------------------------------------------------------------- /unify-kernel: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Derived from safeboot unify-kernel 3 | # Creates a unified kernel image with the named sections and files 4 | # (typically `kernel`, `initrd`, `cmdline`, and `osrel`) bundled into 5 | # an EFI executable. 6 | # 7 | # ' 8 | 9 | usage=' 10 | Usage: 11 | unify-kernel bootx64.efi \ 12 | linux=bzImage \ 13 | initrd=initrd.cpio.xz \ 14 | cmdline=cmdline.txt \ 15 | ... 16 | 17 | To use a different stub than loader.efi, pass in a 18 | stub=/path/to/loader.efi argument. 19 | ' 20 | 21 | die() { echo >&2 "$@" ; exit 1 ; } 22 | warn() { echo >&2 "$@" ; } 23 | 24 | unified="$1" 25 | shift 26 | 27 | if [ -z "$unified" ]; then 28 | die "$usage" 29 | fi 30 | 31 | # "$PREFIX/usr/lib/systemd/boot/efi/linuxx64.efi.stub" \ 32 | STUB="$(dirname $0)/loader.efi" 33 | 34 | sections=() 35 | offset=$((0x20000)) 36 | blocksize=$((0x10000)) 37 | 38 | # Build the list of sections to add, splitting on = signs 39 | for section in "$@"; do 40 | name="${section%=*}" 41 | file="${section#*=}" 42 | if [ "$name" = "$section" ]; then 43 | die "$name: format error (not name=file?)" 44 | fi 45 | if [ ! -r "$file" ]; then 46 | die "$file: unable to read for section $name" 47 | fi 48 | 49 | if [ "$name" = "stub" ]; then 50 | STUB="$file" 51 | continue 52 | fi 53 | 54 | size="$(wc -c < "$file")" 55 | warn ".$name=$file: $size @ $offset" 56 | 57 | sections+=( \ 58 | --add-section ".$name=$file" \ 59 | --change-section-vma ".$name=$offset" \ 60 | ) 61 | 62 | # round up the offset to the next block size 63 | offset="$(( (offset + size + blocksize-1) / blocksize * blocksize ))" 64 | done 65 | 66 | if [ ! -r "$STUB" ]; then 67 | die "Unable to find EFI stub $stub" 68 | fi 69 | 70 | 71 | 72 | objcopy \ 73 | "${sections[@]}" \ 74 | "$STUB" \ 75 | "$unified" \ 76 | || die "$unified: unable to create" 77 | 78 | sha256sum "$unified" 79 | -------------------------------------------------------------------------------- /worldbuilder/__init__.py: -------------------------------------------------------------------------------- 1 | # worldbuilder stuff 2 | 3 | from worldbuilder.submodule import Submodule 4 | from worldbuilder.initrd import Initrd 5 | from worldbuilder.builder import Builder 6 | #from worldbuilder.commands import prefix_map, configure_cmd, kbuild_make 7 | -------------------------------------------------------------------------------- /worldbuilder/builder.py: -------------------------------------------------------------------------------- 1 | # Building envrionment for a set of submodules 2 | # TODO: have this drive the set of modules and name resolution 3 | 4 | from worldbuilder.util import * 5 | from worldbuilder.submodule import global_mods # TODO remove this 6 | #from graphlib import TopologicalSorter # requires python3.9 7 | from worldbuilder.graphlib_backport import TopologicalSorter # our own copy 8 | from threading import Thread 9 | from time import sleep 10 | 11 | class Builder: 12 | def __init__(self, mods): 13 | self.mods = mods 14 | self.failed = False 15 | self.single_thread = False 16 | self.reset() 17 | 18 | def reset(self): 19 | self.waiting = {} 20 | self.building = {} 21 | self.installed = {} 22 | self.failed = {} 23 | 24 | def report(self): 25 | wait_list = ','.join(self.waiting) 26 | building_list = ','.join(self.building) 27 | installed_list = ','.join(self.installed) 28 | failed_list = ','.join(self.failed) 29 | print(now(), 30 | "building=[" + building_list 31 | + "] waiting=[" + wait_list 32 | + "] installed=[" + installed_list 33 | + "]" 34 | ) 35 | if len(self.failed) > 0: 36 | print(now(), "failed=" + failed_list, file=sys.stderr) 37 | return False 38 | 39 | return True 40 | 41 | def _build_thread(self, mod): 42 | 43 | del self.waiting[mod.fullname] 44 | self.building[mod.fullname] = mod 45 | #self.report() 46 | failed = False 47 | 48 | try: 49 | start_time = time.time() 50 | if mod.installed: 51 | # nothing to do! 52 | pass 53 | elif mod.install(): 54 | self.installed[mod.fullname] = mod 55 | print(now(), "DONE " + mod.fullname + " (%d seconds)" % (time.time() - start_time)) 56 | else: 57 | failed = True 58 | 59 | except Exception as e: 60 | print(traceback.format_exc()) #, file=sys.stderr) 61 | failed = True 62 | 63 | if failed: 64 | self.failed[mod.fullname] = mod 65 | print(now(), "FAILED! " + mod.fullname + ": logs are in " + relative(mod.last_logfile)) #, file=sys.stderr) 66 | for line in readfile(mod.last_logfile).split(b'\n')[-20:-1]: 67 | print(mod.fullname + ": " + line.decode('utf-8')) #, file=sys.stderr) 68 | #print(mod.fullname, mod.dict) 69 | 70 | del self.building[mod.fullname] 71 | #self.report() 72 | 73 | def check(self): 74 | # walk all the dependencies to ensure consistency of inputs 75 | self.reset() 76 | 77 | # build the transitive closure of all modules that are 78 | # required, and sort them into a build order so that 79 | # dependencies are maintained 80 | ts = TopologicalSorter() 81 | 82 | for mod in self.mods: 83 | # lookup any strings-based dependencies 84 | depends = [] 85 | if type(mod) == str: 86 | if not mod in global_mods: 87 | die(mod + ": not found?") 88 | mod = global_mods[mod] 89 | 90 | for dep in mod.depends: 91 | if type(dep) == str: 92 | if not dep in global_mods: 93 | die(dep + ": not found? referenced by " + mod.fullname) 94 | dep = global_mods[dep] 95 | depends.append(dep) 96 | 97 | mod.depends = depends 98 | 99 | ts.add(mod, *mod.depends) 100 | for dep in mod.depends: 101 | self.mods.append(dep) 102 | 103 | self.ordered_mods = [*ts.static_order()] 104 | print([x.fullname for x in self.ordered_mods]) 105 | 106 | for mod in self.ordered_mods: 107 | mod.update_hashes() 108 | mod.install(check=True) 109 | if mod.installed: 110 | self.installed[mod.fullname] = mod 111 | else: 112 | self.waiting[mod.fullname] = mod 113 | print(mod.state() + " " + mod.fullname + ": " + relative(mod.out_dir)) 114 | 115 | self.report() 116 | # for modname, mod in self.built.items(): 117 | # print(mod.state() + " " + mod.name + ": " + mod.out_dir) 118 | # for modname, mod in self.waiting.items(): 119 | # print(mod.state() + " " + mod.name + ": " + mod.out_dir) 120 | 121 | 122 | def build_all(self): 123 | if len(self.waiting) == 0: 124 | self.check() 125 | 126 | while True: 127 | if len(self.waiting) == 0 or len(self.failed) != 0: 128 | # no mods left, no builders? we're done! 129 | if len(self.building) == 0: 130 | return self.report() 131 | 132 | # no mods left, and builds are in process, 133 | # wait for completions. is there a better way? 134 | sleep(1) 135 | continue 136 | 137 | if self.single_thread and len(self.building) != 0: 138 | # let's wait for it to finish 139 | sleep(0.1) 140 | continue 141 | 142 | for name in list(self.waiting): 143 | mod = self.waiting[name] 144 | ready = True 145 | for dep in mod.depends: 146 | if not dep.fullname in self.installed: 147 | ready = False 148 | 149 | if not ready: 150 | # oh well, try the next one 151 | continue 152 | 153 | # it is time to build this mod! 154 | mod.building = True 155 | Thread(target = self._build_thread, args=(mod,)).start() 156 | break 157 | 158 | # processed the list of waiting ones sleep for a bit and 159 | # try again in a little while 160 | sleep(0.1) 161 | 162 | def cache_create(self, cache_dir): 163 | self.check() 164 | fail = False 165 | 166 | for dep in self.ordered_mods: 167 | if not dep.cacheable: 168 | continue 169 | if not dep.installed: 170 | print(dep.fullname + ": not ready to build cache", file=sys.stderr) 171 | fail = True 172 | continue 173 | if fail: 174 | return False 175 | 176 | mkdir(cache_dir) 177 | 178 | for dep in self.ordered_mods: 179 | if not dep.cacheable: 180 | continue 181 | dep.cache_create(cache_dir) 182 | 183 | 184 | 185 | if __name__ == "__main__": 186 | pass 187 | -------------------------------------------------------------------------------- /worldbuilder/commands.py: -------------------------------------------------------------------------------- 1 | # Common comands for different build systems 2 | 3 | # some submodules use the same arguments 4 | kbuild_make = [ 5 | "make", 6 | "-C%(src_dir)s", 7 | "O=%(rout_dir)s", 8 | "KBUILD_HOST=builder", 9 | "KBUILD_USER=%(out_hash)s", 10 | "KBUILD_BUILD_TIMESTAMP=1970-01-01", 11 | "KBUILD_BUILD_VERSION=%(src_hash)s", 12 | ] 13 | 14 | configure_cmd = "%(src_dir)s/configure" 15 | 16 | # Try to remove any absolute paths and things that make reproducibility hard 17 | # these are applied in reverse order? 18 | prefix_map = "-gno-record-gcc-switches" \ 19 | + " -Wl,--build-id=none" \ 20 | + " -ffile-prefix-map=%(top_dir)s/out=/build" \ 21 | + " -ffile-prefix-map=%(top_dir)s/src=/src" \ 22 | + " -ffile-prefix-map=%(top_dir)s/install=/" \ 23 | 24 | # + " -ffile-prefix-map=%(src_dir)s=/src/%(name)s-%(version)s" \ 25 | # + " -ffile-prefix-map=%(out_dir)s=/build" \ 26 | 27 | # Some broken configure scripts ignore the `--disable-rpath`, so this 28 | # forcibly rewrites their libtool in place to avoid it. 29 | fix_libtool = [ 30 | 'sed', 31 | '-i', 32 | #'s/hardcode_into_libs=yes/hardcode_into_libs=no/g', 33 | 's/^hardcode_libdir_flag_spec=.*$/hardcode_libdir_flag_spec="-D__LIBTOOL_IS_A_FOOL__"/', 34 | "%(src_dir)s/configure", 35 | ] 36 | 37 | delete_la = [ "find", "%(install_dir)s", "-name", "*.la", "-exec", "rm", "{}", ";" ] 38 | 39 | strip_libs = [ "find", "%(lib_dir)s", "-name", "*.so", "-a", "-type", "f", "-exec", "strip", "{}", ";" ] 40 | 41 | -------------------------------------------------------------------------------- /worldbuilder/coreboot.py: -------------------------------------------------------------------------------- 1 | # coreboot is such a bear that it gets its own python module 2 | # and the crosscompiler is required 3 | 4 | from worldbuilder import Submodule 5 | from worldbuilder import commands 6 | from worldbuilder.util import * 7 | 8 | versions = { 9 | "4.8.1": { 10 | "tarhash": "f0ddf4db0628c1fe1e8348c40084d9cbeb5771400c963fd419cda3995b69ad23", 11 | "blobs_hash": "18aa509ae3af005a05d7b1e0b0246dc640249c14fc828f5144b6fd20bb10e295", 12 | }, 13 | "4.11": { 14 | "tarhash": "97fd859b4c39a25534fe33c30eb86e54a233952e08a024c55858d11598a8ad87", 15 | "blobs_hash": "aa7855c5bd385b3360dadc043ea6bc93f564e6e4840d9b3ee5b9e696bbd055db", 16 | }, 17 | "4.13": { 18 | "tarhash": "4779da645a25ddebc78f1bd2bd0b740fb1e6479572648d4650042a2b9502856a", 19 | "blobs_hash": "060656b46a7859d038ddeec3f7e086e85f146a50b280c4babec23c1188264dc8", 20 | }, 21 | "4.15": { 22 | "tarhash": "20e6aaa6dd0eaec7753441c799711d1b4630e3ca709536386f2242ac2c8a1ec5", 23 | "blobs_hash": "c0e2d8006da226208ba274a44895d102cb2879cf139cc67bba5f62e67b871f6d", 24 | #"extra_flags": "-fdebug-prefix-map=$(pwd)=heads -gno-record-gcc-switches -Wno-error=packed-not-aligned -Wno-error=address-of-packed-member -Wno-error", 25 | }, 26 | } 27 | 28 | 29 | 30 | def CorebootSrc( 31 | version, 32 | patches = None, 33 | tarhash = None, 34 | blobhash = None, 35 | ): 36 | if not tarhash: 37 | if version not in versions: 38 | warn("coreboot " + version + " is unknown") 39 | else: 40 | tarhash = versions[version]["tarhash"] 41 | blobhash = versions[version]["blobs_hash"] 42 | 43 | src = Submodule( 44 | "coreboot-" + version, 45 | version = version, 46 | #depends = [ "gcc32", "iasl" ], 47 | url = "https://www.coreboot.org/releases/coreboot-%(version)s.tar.xz", 48 | tarhash = tarhash, 49 | patches = patches, 50 | ) 51 | 52 | # the src depends on the blobs so that the return from the function 53 | # can be the src tree, which will be ready to try compiling once 54 | # things are ready. 55 | blobs = Submodule( 56 | "coreboot_blobs-" + version, 57 | version = version, 58 | depends = [ src ], 59 | url = "https://www.coreboot.org/releases/coreboot-blobs-%(version)s.tar.xz", 60 | tarhash = blobhash, 61 | strip_components = 3, 62 | install = [ 63 | "ln", "-sf", 64 | "%(src_dir)s", 65 | "%(" + src.name + ".src_dir)s/3rdparty/blobs", 66 | ], 67 | ) 68 | 69 | return src 70 | 71 | def Coreboot( 72 | name, 73 | src = None, 74 | config = None, 75 | initrd = None, 76 | kernel = None, 77 | compiler = None, 78 | ): 79 | if not config or not initrd or not kernel or not compiler: 80 | die(name + ": coreboot requires config,initrd, kernel and crosscompiler") 81 | 82 | if type(initrd) == str: 83 | initrd_name = initrd 84 | else: 85 | initrd_name = initrd.name 86 | 87 | if type(kernel) == str: 88 | kernel_name = kernel 89 | else: 90 | kernel_name = kernel.name 91 | 92 | if type(src) == str: 93 | coreboot_name = src 94 | (stub,coreboot_version) = coreboot_name.rsplit('-', 1) 95 | else: 96 | coreboot_name = src.name 97 | coreboot_version = src.version 98 | 99 | initrd_file = '%(' + initrd_name + '.install_dir)s/initrd.cpio.xz' 100 | kernel_file = '%(' + kernel_name + '.install_dir)s/bzImage' 101 | 102 | extra_env = [ 103 | "V=1", 104 | "BUILD_TIMELESS=1", 105 | "obj=%(out_dir)s/" + name, 106 | "DOTCONFIG=%(out_dir)s/.config", 107 | "IASL=%(iasl.bin_dir)s/iasl", 108 | "CROSS_COMPILE_x86=" + compiler.cross32, 109 | "CROSS_COMPILE_x64=" + compiler.cross, 110 | "CC_x86_32=" + compiler.cross32 + "gcc", 111 | "CC_x86_64=" + compiler.cross + "gcc", 112 | "CFLAGS_x86_32=" 113 | + "-Wno-error=packed-not-aligned -Wno-error=address-of-packed-member " 114 | + commands.prefix_map, 115 | *compiler.cross_tools32_nocc, 116 | ] 117 | 118 | return Submodule( 119 | "coreboot-" + name, 120 | version = coreboot_version, 121 | depends = [ 122 | initrd, 123 | kernel, 124 | src, 125 | "coreboot_blobs-" + coreboot_version, 126 | "gcc32", 127 | "iasl", 128 | ], 129 | config_files = [ config ], 130 | dep_files = [ initrd_file, kernel_file ], 131 | 132 | # turn off the config file inclusion so that paths for the 133 | # initrd and bzimage don't end up in the rom image. 134 | config_append = [ 135 | 'CONFIG_INCLUDE_CONFIG_FILE=n', 136 | 'CONFIG_LINUX_INITRD="' + initrd_file + '"', 137 | 'CONFIG_PAYLOAD_FILE="' + kernel_file + '"', 138 | 'CONFIG_LOCALVERSION="%(out_hash)s"', 139 | 'CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME="' + name + '"', 140 | ], 141 | 142 | configure = [ "bash", "-c", " ".join([ 143 | *make_env(extra_env), 144 | "make", 145 | "olddefconfig", 146 | "-C%("+coreboot_name+".src_dir)s", 147 | ])], 148 | 149 | # work around a bug in make that doesn't pass command line vars in the environment 150 | # which prevents the local iasl binary from being used by subshells 151 | make = [ "bash", "-c", " ".join([ 152 | *make_env(extra_env), 153 | "make", 154 | "-C%("+coreboot_name+".src_dir)s", 155 | ])], 156 | 157 | install = [ 158 | "cp", name+"/coreboot.rom", "%(bin_dir)s/coreboot-"+name+".rom", 159 | ], 160 | 161 | #install_dir = '', 162 | bin_dir = '', 163 | 164 | bins = [ "coreboot-"+ name + ".rom" ], 165 | report_hashes = True, 166 | ) 167 | 168 | """ 169 | $(build)/$(BOARD)/$(CB_OUTPUT_FILE): $(build)/$(coreboot_dir)/.build 170 | # Use coreboot.rom, because custom output files might not be processed by cbfstool 171 | "$(build)/$(coreboot_dir)/cbfstool" "$(dir $<)coreboot.rom" print 172 | $(call do-copy,$(dir $<)$(CONFIG_COREBOOT_ROM),$@) 173 | @touch $@ # update the time stamp 174 | 175 | ifneq ($(CONFIG_COREBOOT_BOOTBLOCK),) 176 | $(build)/$(BOARD)/$(CB_BOOTBLOCK_FILE): $(build)/$(coreboot_dir)/.build 177 | $(call do-copy,$(dir $<)$(CONFIG_COREBOOT_BOOTBLOCK),$@) 178 | @touch $@ # update the time stamp 179 | endif 180 | 181 | endif 182 | 183 | # 184 | # Helpful target for reconfiguring the coreboot target 185 | # 186 | coreboot.menuconfig: 187 | $(MAKE) \ 188 | -C "$(build)/$(coreboot_base_dir)" \ 189 | DOTCONFIG="$(build)/$(coreboot_dir)/.config" \ 190 | menuconfig 191 | 192 | # The config file in the repo is stored as a "defconfig" format 193 | # which only includes the options that have changed from the defaults. 194 | coreboot.saveconfig: 195 | $(MAKE) \ 196 | -C "$(build)/$(coreboot_base_dir)" \ 197 | DOTCONFIG="$(build)/$(coreboot_dir)/.config" \ 198 | DEFCONFIG="$(pwd)/$(CONFIG_COREBOOT_CONFIG)" \ 199 | savedefconfig 200 | 201 | 202 | # if we are not building from a git checkout, 203 | # we must also download the coreboot-blobs tree 204 | ifneq "$(coreboot_version)" "git" 205 | 206 | coreboot_depends += coreboot-blobs 207 | modules-y += coreboot-blobs 208 | 209 | coreboot-blobs_version := $(coreboot_version) 210 | coreboot-blobs_tar := coreboot-blobs-$(coreboot-blobs_version).tar.xz 211 | coreboot-blobs_url := https://www.coreboot.org/releases/$(coreboot-blobs_tar) 212 | 213 | 214 | ## there is nothing to build for the blobs, this should be 215 | ## made easier to make happen 216 | coreboot-blobs_output := .built 217 | coreboot-blobs_configure := echo -e 'all:\n\ttouch .built' > Makefile 218 | 219 | endif 220 | endif 221 | """ 222 | -------------------------------------------------------------------------------- /worldbuilder/crosscompile.py: -------------------------------------------------------------------------------- 1 | # Build a GCC cross compiler 2 | # 3 | import worldbuilder 4 | from worldbuilder import commands 5 | 6 | target_arch = "x86_64-linux-musl" 7 | target_arch32 = "i386-linux-musl" 8 | 9 | gmp = worldbuilder.Submodule("gmp", 10 | version = "6.2.1", 11 | url = "https://ftp.gnu.org/gnu/%(name)s/%(name)s-%(version)s.tar.xz", 12 | tarhash = 'fd4829912cddd12f84181c3451cc752be224643e87fac497b69edddadc49b4f2', 13 | cacheable = True, 14 | configure = [ 15 | commands.configure_cmd, 16 | "--prefix=/", 17 | "--enable-static=yes", 18 | "--enable-shared=no", 19 | "PKG_CONFIG=/bin/false", 20 | "CFLAGS=" + commands.prefix_map, 21 | ], 22 | make = [ "make" ], 23 | install = [ 24 | [ "make", "install", "DESTDIR=%(install_dir)s", ], 25 | commands.delete_la, 26 | ], 27 | ) 28 | 29 | mpfr = worldbuilder.Submodule("mpfr", 30 | depends = [ "gmp" ], 31 | version = "4.1.0", 32 | url = "https://ftp.gnu.org/gnu/%(name)s/%(name)s-%(version)s.tar.xz", 33 | tarhash = '0c98a3f1732ff6ca4ea690552079da9c597872d30e96ec28414ee23c95558a7f', 34 | cacheable = True, 35 | configure = [ 36 | commands.configure_cmd, 37 | "--prefix=/", 38 | "--enable-static=yes", 39 | "--enable-shared=no", 40 | "--with-gmp=%(gmp.install_dir)s", 41 | "PKG_CONFIG=/bin/false", 42 | "CFLAGS=" + commands.prefix_map, 43 | ], 44 | install = [ 45 | [ "make", "install", "DESTDIR=%(install_dir)s", ], 46 | commands.delete_la, 47 | ], 48 | ) 49 | 50 | mpc = worldbuilder.Submodule("mpc", 51 | depends = [ "mpfr", "gmp" ], 52 | version = "1.2.1", 53 | url = "https://ftp.gnu.org/gnu/%(name)s/%(name)s-%(version)s.tar.gz", 54 | tarhash = '17503d2c395dfcf106b622dc142683c1199431d095367c6aacba6eec30340459', 55 | cacheable = True, 56 | configure = [ 57 | commands.configure_cmd, 58 | "--prefix=/", 59 | "--with-mpfr=%(mpfr.install_dir)s", 60 | "--with-gmp=%(gmp.install_dir)s", 61 | "--enable-static=yes", 62 | "--enable-shared=no", 63 | "PKG_CONFIG=/bin/false", 64 | "CFLAGS=" + commands.prefix_map, 65 | ], 66 | make = [ "make" ], 67 | install = [ 68 | [ "make", "install", "DESTDIR=%(install_dir)s", ], 69 | commands.delete_la, 70 | ], 71 | ) 72 | 73 | binutils_src = worldbuilder.Submodule("binutils_src", 74 | version = "2.38", 75 | cacheable = True, 76 | url = "https://ftp.gnu.org/gnu/binutils/binutils-%(version)s.tar.xz", 77 | tarhash = 'e316477a914f567eccc34d5d29785b8b0f5a10208d36bbacedcc39048ecfe024', 78 | ) 79 | 80 | binutils = worldbuilder.Submodule("binutils", 81 | depends = [ mpc, binutils_src ], 82 | version = binutils_src.version, 83 | cacheable = True, 84 | configure = [ 85 | "%(binutils_src.src_dir)s/configure", 86 | "--target=" + target_arch, 87 | "--prefix=/", 88 | "--with-mpc=%(mpc.install_dir)s", 89 | "--disable-nls", 90 | "PKG_CONFIG=/bin/false", 91 | "CFLAGS=" + commands.prefix_map, 92 | ], 93 | make = [ "make" ], 94 | install = [ "make", "install", "DESTDIR=%(install_dir)s", ], 95 | ) 96 | 97 | binutils32 = worldbuilder.Submodule("binutils32", 98 | depends = [ mpc, binutils_src ], 99 | version = binutils_src.version, 100 | cacheable = True, 101 | configure = [ 102 | "%(binutils_src.src_dir)s/configure", 103 | "--target=" + target_arch32, 104 | "--prefix=/", 105 | "--with-mpc=%(mpc.install_dir)s", 106 | "--disable-nls", 107 | "PKG_CONFIG=/bin/false", 108 | "CFLAGS=" + commands.prefix_map, 109 | ], 110 | make = [ "make" ], 111 | install = [ "make", "install", "DESTDIR=%(install_dir)s", ], 112 | ) 113 | 114 | bison = worldbuilder.Submodule("bison", 115 | version = "3.8.2", 116 | url = "https://ftp.gnu.org/gnu/%(name)s/%(name)s-%(version)s.tar.xz", 117 | tarhash = '9bba0214ccf7f1079c5d59210045227bcf619519840ebfa80cd3849cff5a5bf2', 118 | configure = [ 119 | commands.configure_cmd, 120 | "--prefix=/", 121 | "PKG_CONFIG=/bin/false", 122 | "CFLAGS=" + commands.prefix_map, 123 | ], 124 | make = [ "make" ], 125 | install = [ "make", "install", "DESTDIR=%(install_dir)s", ], 126 | ) 127 | 128 | cross = "%(binutils.install_dir)s/bin/" + target_arch + "-" 129 | cross32 = "%(binutils32.install_dir)s/bin/" + target_arch32 + "-" 130 | 131 | tools = "ar as ld nm ranlib objcopy objdump strip".split(" ") 132 | 133 | # these are for gcc's special "FOO_FOR_TARGET" instead of "FOO" 134 | gcc_cross_tools = [x.upper() + "_FOR_TARGET=" + cross + x 135 | for x in tools] 136 | gcc_cross32_tools = [x.upper() + "_FOR_TARGET=" + cross32 + x 137 | for x in tools] 138 | 139 | cross_tools_nocc = [x.upper() + "=" + cross + x 140 | for x in tools] 141 | cross_tools32_nocc = [x.upper() + "=" + cross32 + x 142 | for x in tools] 143 | 144 | cross_gcc = "%(musl.install_dir)s/bin/musl-gcc" 145 | cross_tools = [ 146 | "CC="+cross_gcc, 147 | "CXX="+cross_gcc, 148 | "PKG_CONFIG=/bin/false", # ensure that nothing comes the system 149 | *cross_tools_nocc, 150 | ] 151 | 152 | cross_tools32 = [ 153 | "CC=%(musl32.install_dir)s/bin/musl-gcc", 154 | "CXX=%(musl32.install_dir)s/bin/musl-gcc", 155 | *cross_tools32_nocc, 156 | ] 157 | 158 | gcc_version = "11.2.0" 159 | 160 | # this fakes the install into the binutils directory to avoid issues later 161 | crossgcc_src = worldbuilder.Submodule("crossgcc_src", 162 | url = "https://ftp.gnu.org/gnu/gcc/gcc-%(version)s/gcc-%(version)s.tar.xz", 163 | cacheable = True, 164 | #version = "9.4.0", 165 | #tarhash = 'c95da32f440378d7751dd95533186f7fc05ceb4fb65eb5b85234e6299eb9838e', 166 | version = gcc_version, 167 | tarhash = 'd08edc536b54c372a1010ff6619dd274c0f1603aa49212ba20f7aa2cda36fa8b', 168 | ) 169 | 170 | # submodule must also provide `--target=....` 171 | crossgcc_configure_cmds = [ 172 | "%(crossgcc_src.src_dir)s/configure", 173 | "--with-mpc=%(mpc.install_dir)s", 174 | "--with-gmp=%(gmp.install_dir)s", 175 | "--with-mpfr=%(mpfr.install_dir)s", 176 | "--enable-languages=c", 177 | "--without-headers", 178 | "--with-newlib", 179 | "--disable-nls", 180 | "--disable-plugin", 181 | "--disable-lto", 182 | "--disable-multilib", 183 | "--disable-decimal-float", 184 | "--disable-libmudflap", 185 | "--disable-libssp", 186 | "--disable-libgomp", 187 | "--disable-libquadmath", 188 | "CFLAGS=" + commands.prefix_map, 189 | ] 190 | 191 | crossgcc = worldbuilder.Submodule("crossgcc", 192 | version = crossgcc_src.version, 193 | depends = [ binutils, mpc, mpfr, gmp, crossgcc_src, ], 194 | cacheable = True, 195 | configure = [ 196 | *crossgcc_configure_cmds, 197 | "--target", target_arch, 198 | "--prefix=/", 199 | "--with-build-time-tools=%(binutils.install_dir)s/bin", 200 | *gcc_cross_tools, 201 | "PKG_CONFIG=/bin/false", 202 | ], 203 | make = [ "make", "all-gcc" ], 204 | install = [ "make", "install-gcc", "DESTDIR=%(binutils.install_dir)s", ], 205 | ) 206 | 207 | crossgcc32 = worldbuilder.Submodule("crossgcc32", 208 | version = crossgcc_src.version, 209 | depends = [ binutils32, mpc, mpfr, gmp, crossgcc_src, ], 210 | cacheable = True, 211 | configure = [ 212 | *crossgcc_configure_cmds, 213 | "--target=" + target_arch32, 214 | "--prefix=/", 215 | "--with-build-time-tools=%(binutils32.install_dir)s/bin", 216 | *gcc_cross32_tools, 217 | "PKG_CONFIG=/bin/false", 218 | ], 219 | make = [ "make", "all-gcc" ], 220 | install = [ "make", "install-gcc", "DESTDIR=%(binutils32.install_dir)s", ], 221 | ) 222 | 223 | musl_src = worldbuilder.Submodule("musl_src", 224 | version = "1.2.2", 225 | url = "https://musl.libc.org/releases/musl-%(version)s.tar.gz", 226 | tarhash = '9b969322012d796dc23dda27a35866034fa67d8fb67e0e2c45c913c3d43219dd', 227 | patches = [ "patches/musl-%(version)s/*.patch" ], 228 | 229 | # source only; don't build anything 230 | ) 231 | 232 | musl_configure_cmds = [ 233 | "%(musl_src.src_dir)s/configure", 234 | "--prefix=/", 235 | "--syslibdir=/lib", 236 | "--enable-wrapper=gcc", 237 | ] 238 | 239 | musl = worldbuilder.Submodule("musl", 240 | depends = [ crossgcc, musl_src ], 241 | version = musl_src.version, 242 | cacheable = True, 243 | configure = [ 244 | *musl_configure_cmds, 245 | "--target=" + target_arch, 246 | "CC=" + cross + "gcc", 247 | "CFLAGS=" 248 | + "-ffast-math -O3 " # avoid libgcc circular math dependency 249 | + commands.prefix_map, 250 | "PKG_CONFIG=/bin/false", 251 | *cross_tools_nocc, 252 | ], 253 | make = [ 254 | "make", 255 | "LDSO_PATHNAME=/lib/ld-musl-x86_64.so.1", 256 | "WRAPCC_GCC=$$MUSL_TOP/../../binutils-%(binutils.version)s/%(binutils.out_hash)s/bin/"+target_arch+"-gcc", 257 | ], 258 | install = [ 259 | "make", 260 | "install", 261 | "DESTDIR=%(install_dir)s", 262 | ], 263 | 264 | libs = [ "libc.so" ], 265 | ) 266 | 267 | musl32 = worldbuilder.Submodule("musl32", 268 | depends = [ crossgcc32, musl_src ], 269 | version = musl_src.version, 270 | cacheable = True, 271 | configure = [ 272 | *musl_configure_cmds, 273 | "--target=" + target_arch32, 274 | "CC=" + cross32 + "gcc", 275 | "CFLAGS=" 276 | + "-ffast-math -O3 " # avoid libgcc circular math dependency 277 | + commands.prefix_map, 278 | "PKG_CONFIG=/bin/false", 279 | "LDFLAGS=-Wl,--unresolved-symbols=ignore-in-object-files", # also libgcc issue 280 | *cross_tools32_nocc, 281 | ], 282 | make = [ 283 | "make", 284 | "LDSO_PATHNAME=/lib/ld-musl-i386.so.1", 285 | "WRAPCC_GCC=$$MUSL_TOP/../../%(binutils32.fullname)s/%(binutils32.out_hash)s/bin/"+target_arch32+"-gcc", 286 | ], 287 | install = [ 288 | "make", 289 | "install", 290 | "DESTDIR=%(install_dir)s", 291 | ], 292 | 293 | libs = [ "libc.so" ], 294 | ) 295 | 296 | # pick up in the cross gcc target once musl has been built so that 297 | # libgcc can use the musl headers to build. This is a fake package 298 | # with no source; it simply runs another command in the crossgcc tree 299 | # to build the libgcc library once musl headers are available 300 | # it is named gcc to be easier to refer to 301 | gcc = worldbuilder.Submodule("gcc", 302 | version = crossgcc_src.version, 303 | depends = [ crossgcc, musl ], 304 | cacheable = True, 305 | make = [ 306 | "make", 307 | "-C", "%(crossgcc.out_dir)s", 308 | "all-target-libgcc", 309 | "CFLAGS=" + commands.prefix_map, 310 | "CFLAGS_FOR_TARGET=" 311 | + "-I%(musl.install_dir)s/include " 312 | + "-B%(musl.install_dir)s/lib " 313 | + commands.prefix_map, 314 | "PKG_CONFIG=/bin/false", 315 | *gcc_cross_tools, 316 | ], 317 | install = [ 318 | "make", 319 | "-C", "%(crossgcc.out_dir)s", 320 | "install-target-libgcc", 321 | "DESTDIR=%(binutils.install_dir)s", 322 | ], 323 | ) 324 | 325 | gcc32 = worldbuilder.Submodule("gcc32", 326 | version = crossgcc_src.version, 327 | depends = [ crossgcc32, musl32 ], 328 | cacheable = True, 329 | make = [ 330 | "make", 331 | "-C", "%(crossgcc32.out_dir)s", 332 | "all-target-libgcc", 333 | "CFLAGS=" + commands.prefix_map, 334 | "CFLAGS_FOR_TARGET=" 335 | + "-I%(musl32.install_dir)s/include " 336 | + "-B%(musl32.install_dir)s/lib " 337 | + commands.prefix_map, 338 | "PKG_CONFIG=/bin/false", 339 | *gcc_cross32_tools, 340 | ], 341 | install = [ 342 | "make", 343 | "-C", "%(crossgcc32.out_dir)s", 344 | "install-target-libgcc", 345 | "DESTDIR=%(binutils32.install_dir)s", 346 | ], 347 | ) 348 | 349 | libgcc32 = "%(binutils32.lib_dir)s/gcc/"+target_arch32+"/%(gcc32.version)s/libgcc.a" 350 | libgcc = "%(binutils.lib_dir)s/gcc/"+target_arch+"/%(gcc.version)s/libgcc.a" 351 | -------------------------------------------------------------------------------- /worldbuilder/graphlib_backport.py: -------------------------------------------------------------------------------- 1 | __all__ = ["TopologicalSorter", "CycleError"] 2 | 3 | _NODE_OUT = -1 4 | _NODE_DONE = -2 5 | 6 | 7 | class _NodeInfo: 8 | __slots__ = "node", "npredecessors", "successors" 9 | 10 | def __init__(self, node): 11 | # The node this class is augmenting. 12 | self.node = node 13 | 14 | # Number of predecessors, generally >= 0. When this value falls to 0, 15 | # and is returned by get_ready(), this is set to _NODE_OUT and when the 16 | # node is marked done by a call to done(), set to _NODE_DONE. 17 | self.npredecessors = 0 18 | 19 | # List of successor nodes. The list can contain duplicated elements as 20 | # long as they're all reflected in the successor's npredecessors attribute). 21 | self.successors = [] 22 | 23 | 24 | class CycleError(ValueError): 25 | """Subclass of ValueError raised by TopologicalSorterif cycles exist in the graph 26 | 27 | If multiple cycles exist, only one undefined choice among them will be reported 28 | and included in the exception. The detected cycle can be accessed via the second 29 | element in the *args* attribute of the exception instance and consists in a list 30 | of nodes, such that each node is, in the graph, an immediate predecessor of the 31 | next node in the list. In the reported list, the first and the last node will be 32 | the same, to make it clear that it is cyclic. 33 | """ 34 | 35 | pass 36 | 37 | 38 | class TopologicalSorter: 39 | """Provides functionality to topologically sort a graph of hashable nodes""" 40 | 41 | def __init__(self, graph=None): 42 | self._node2info = {} 43 | self._ready_nodes = None 44 | self._npassedout = 0 45 | self._nfinished = 0 46 | 47 | if graph is not None: 48 | for node, predecessors in graph.items(): 49 | self.add(node, *predecessors) 50 | 51 | def _get_nodeinfo(self, node): 52 | result = self._node2info.get(node) 53 | if result is None: 54 | self._node2info[node] = result = _NodeInfo(node) 55 | return result 56 | 57 | def add(self, node, *predecessors): 58 | """Add a new node and its predecessors to the graph. 59 | 60 | Both the *node* and all elements in *predecessors* must be hashable. 61 | 62 | If called multiple times with the same node argument, the set of dependencies 63 | will be the union of all dependencies passed in. 64 | 65 | It is possible to add a node with no dependencies (*predecessors* is not provided) 66 | as well as provide a dependency twice. If a node that has not been provided before 67 | is included among *predecessors* it will be automatically added to the graph with 68 | no predecessors of its own. 69 | 70 | Raises ValueError if called after "prepare". 71 | """ 72 | if self._ready_nodes is not None: 73 | raise ValueError("Nodes cannot be added after a call to prepare()") 74 | 75 | # Create the node -> predecessor edges 76 | nodeinfo = self._get_nodeinfo(node) 77 | nodeinfo.npredecessors += len(predecessors) 78 | 79 | # Create the predecessor -> node edges 80 | for pred in predecessors: 81 | pred_info = self._get_nodeinfo(pred) 82 | pred_info.successors.append(node) 83 | 84 | def prepare(self): 85 | """Mark the graph as finished and check for cycles in the graph. 86 | 87 | If any cycle is detected, "CycleError" will be raised, but "get_ready" can 88 | still be used to obtain as many nodes as possible until cycles block more 89 | progress. After a call to this function, the graph cannot be modified and 90 | therefore no more nodes can be added using "add". 91 | """ 92 | if self._ready_nodes is not None: 93 | raise ValueError("cannot prepare() more than once") 94 | 95 | self._ready_nodes = [ 96 | i.node for i in self._node2info.values() if i.npredecessors == 0 97 | ] 98 | # ready_nodes is set before we look for cycles on purpose: 99 | # if the user wants to catch the CycleError, that's fine, 100 | # they can continue using the instance to grab as many 101 | # nodes as possible before cycles block more progress 102 | cycle = self._find_cycle() 103 | if cycle: 104 | raise CycleError(f"nodes are in a cycle", cycle) 105 | 106 | def get_ready(self): 107 | """Return a tuple of all the nodes that are ready. 108 | 109 | Initially it returns all nodes with no predecessors; once those are marked 110 | as processed by calling "done", further calls will return all new nodes that 111 | have all their predecessors already processed. Once no more progress can be made, 112 | empty tuples are returned. 113 | 114 | Raises ValueError if called without calling "prepare" previously. 115 | """ 116 | if self._ready_nodes is None: 117 | raise ValueError("prepare() must be called first") 118 | 119 | # Get the nodes that are ready and mark them 120 | result = tuple(self._ready_nodes) 121 | n2i = self._node2info 122 | for node in result: 123 | n2i[node].npredecessors = _NODE_OUT 124 | 125 | # Clean the list of nodes that are ready and update 126 | # the counter of nodes that we have returned. 127 | self._ready_nodes.clear() 128 | self._npassedout += len(result) 129 | 130 | return result 131 | 132 | def is_active(self): 133 | """Return True if more progress can be made and ``False`` otherwise. 134 | 135 | Progress can be made if cycles do not block the resolution and either there 136 | are still nodes ready that haven't yet been returned by "get_ready" or the 137 | number of nodes marked "done" is less than the number that have been returned 138 | by "get_ready". 139 | 140 | Raises ValueError if called without calling "prepare" previously. 141 | """ 142 | if self._ready_nodes is None: 143 | raise ValueError("prepare() must be called first") 144 | return self._nfinished < self._npassedout or bool(self._ready_nodes) 145 | 146 | def __bool__(self): 147 | return self.is_active() 148 | 149 | def done(self, *nodes): 150 | """Marks a set of nodes returned by "get_ready" as processed. 151 | 152 | This method unblocks any successor of each node in *nodes* for being returned 153 | in the future by a a call to "get_ready" 154 | 155 | Raises :exec:`ValueError` if any node in *nodes* has already been marked as 156 | processed by a previous call to this method, if a node was not added to the 157 | graph by using "add" or if called without calling "prepare" previously or if 158 | node has not yet been returned by "get_ready". 159 | """ 160 | 161 | if self._ready_nodes is None: 162 | raise ValueError("prepare() must be called first") 163 | 164 | n2i = self._node2info 165 | 166 | for node in nodes: 167 | 168 | # Check if we know about this node (it was added previously using add() 169 | nodeinfo = n2i.get(node) 170 | if nodeinfo is None: 171 | raise ValueError(f"node {node!r} was not added using add()") 172 | 173 | # If the node has not being returned (marked as ready) previously, inform the user. 174 | stat = nodeinfo.npredecessors 175 | if stat != _NODE_OUT: 176 | if stat >= 0: 177 | raise ValueError( 178 | f"node {node!r} was not passed out (still not ready)" 179 | ) 180 | elif stat == _NODE_DONE: 181 | raise ValueError(f"node {node!r} was already marked done") 182 | else: 183 | assert False, f"node {node!r}: unknown status {stat}" 184 | 185 | # Mark the node as processed 186 | nodeinfo.npredecessors = _NODE_DONE 187 | 188 | # Go to all the successors and reduce the number of predecessors, collecting all the ones 189 | # that are ready to be returned in the next get_ready() call. 190 | for successor in nodeinfo.successors: 191 | successor_info = n2i[successor] 192 | successor_info.npredecessors -= 1 193 | if successor_info.npredecessors == 0: 194 | self._ready_nodes.append(successor) 195 | self._nfinished += 1 196 | 197 | def _find_cycle(self): 198 | n2i = self._node2info 199 | stack = [] 200 | itstack = [] 201 | seen = set() 202 | node2stacki = {} 203 | 204 | for node in n2i: 205 | if node in seen: 206 | continue 207 | 208 | while True: 209 | if node in seen: 210 | # If we have seen already the node and is in the 211 | # current stack we have found a cycle. 212 | if node in node2stacki: 213 | return stack[node2stacki[node] :] + [node] 214 | # else go on to get next successor 215 | else: 216 | seen.add(node) 217 | itstack.append(iter(n2i[node].successors).__next__) 218 | node2stacki[node] = len(stack) 219 | stack.append(node) 220 | 221 | # Backtrack to the topmost stack entry with 222 | # at least another successor. 223 | while stack: 224 | try: 225 | node = itstack[-1]() 226 | break 227 | except StopIteration: 228 | del node2stacki[stack.pop()] 229 | itstack.pop() 230 | else: 231 | break 232 | return None 233 | 234 | def static_order(self): 235 | """Returns an iterable of nodes in a topological order. 236 | 237 | The particular order that is returned may depend on the specific 238 | order in which the items were inserted in the graph. 239 | 240 | Using this method does not require to call "prepare" or "done". If any 241 | cycle is detected, :exc:`CycleError` will be raised. 242 | """ 243 | self.prepare() 244 | while self.is_active(): 245 | node_group = self.get_ready() 246 | yield from node_group 247 | self.done(*node_group) 248 | -------------------------------------------------------------------------------- /worldbuilder/initrd.py: -------------------------------------------------------------------------------- 1 | # an in-memory initrd builder 2 | import cpiofile 3 | import os 4 | import sys 5 | 6 | from worldbuilder.util import * 7 | from worldbuilder.submodule import Submodule 8 | 9 | class Initrd(Submodule): 10 | def __init__(self, 11 | name, 12 | version = "0.0.1", 13 | filename = "initrd.cpio", 14 | depends = None, 15 | dirs = None, 16 | files = None, 17 | symlinks = None, 18 | devices = None, 19 | add_hashes = True, 20 | ): 21 | super().__init__( 22 | 'initrd-' + name, 23 | depends = depends, 24 | version = version, 25 | ) 26 | self.filename = filename 27 | self.dirs = dirs or [] 28 | self.files = files or [] 29 | self.symlinks = symlinks or [] 30 | self.devices = devices or [] 31 | self.add_hashes = add_hashes 32 | 33 | # make sure that we depend on any files that we bring in 34 | for files in self.files: 35 | for f in files[1:]: 36 | self.dep_files.append(f) 37 | 38 | # todo: we should also depend on our output to force rebuilds 39 | 40 | def fetch(self, check=False): 41 | self.fetched = True 42 | return self 43 | def unpack(self, check=False): 44 | self.unpacked = True 45 | return self 46 | def patched(self, check=False): 47 | self.patched = True 48 | return self 49 | 50 | def compute_src_hash(self): 51 | self.src_hash = sha256hex((self.filename + "-" + self.version).encode('utf-8')) 52 | 53 | def compute_out_hash(self, config_file_hash = zero_hash): 54 | # update our output hash based on our dependencies and our files 55 | dirs_hash = extend(zero_hash, self.dirs) 56 | 57 | files_hash = zero_hash 58 | for files in self.files: 59 | files_hash = extend(files_hash, files) 60 | 61 | symlink_hash = zero_hash 62 | for symlink in self.symlinks: 63 | symlink_hash = extend(symlink_hash, symlink) 64 | 65 | devices_hash = zero_hash 66 | for device in self.devices: 67 | s = [ device[0], device[1], str(device[2]), str(device[3]) ] 68 | devices_hash = extend(devices_hash, s) 69 | 70 | config_file_hash = extend(config_file_hash,[dirs_hash, files_hash, symlink_hash, devices_hash]) 71 | 72 | # update our output hash and all of our state variables 73 | return super().compute_out_hash(config_file_hash) 74 | 75 | def add_file(self, dir_name, encoded_name, dep=None): 76 | if not dep: 77 | dep = self 78 | fullname = dep.format(encoded_name) 79 | 80 | if not exists(fullname): 81 | print("FAIL " + dep.name + ": file not found " + relative(fullname), file=sys.stderr) 82 | return False 83 | 84 | image = readfile(fullname) 85 | mode = 0o700 # os.stat(fullname).st_mode # we're all root here 86 | file_hash = sha256hex(image) 87 | 88 | # quick check for path names 89 | if image.find(b'/home/ubuntu') != -1: 90 | print(relative(fullname) + ": contains full path name", file=sys.stderr) 91 | 92 | self.cpio.add(dir_name, fullname, data=image, mode=mode) 93 | 94 | return file_hash 95 | 96 | # recursively add dependencies 97 | def add_deps(self, depends): 98 | fail = False 99 | 100 | for dep in depends: 101 | if dep.name in self.visited: 102 | continue 103 | 104 | self.visited[dep.name] = 1 105 | 106 | for filename in dep.bins: 107 | file_hash = self.add_file("/bin", filename, dep=dep) 108 | if not file_hash: 109 | fail = True 110 | self.hashes.append(relative(filename) + ": " + (file_hash or "MISSING")) 111 | for filename in dep.libs: 112 | file_hash = self.add_file("/lib", filename, dep=dep) 113 | if not file_hash: 114 | fail = True 115 | self.hashes.append(relative(filename) + ": " + (file_hash or "MISSING")) 116 | 117 | if not self.add_deps(dep.depends): 118 | fail = True 119 | 120 | return not fail 121 | 122 | 123 | def build(self, force=False, check=False): 124 | if not self.configure(check=check): 125 | return False 126 | 127 | build_canary = os.path.join(self.out_dir, ".build-" + self.name) 128 | if not self.build_required(force, build_canary): 129 | self.built = True 130 | return self 131 | if check: 132 | return False 133 | 134 | self.cpio = cpiofile.CPIO() 135 | 136 | # first thing make any directories 137 | for dirname in self.dirs: 138 | self.cpio.mkdir(dirname) 139 | 140 | self.hashes = [] 141 | 142 | # add any binaries and libraries from dependencies 143 | self.visited = {} 144 | fail = not self.add_deps(self.depends) 145 | 146 | # add any additional ones they have requested 147 | for files in self.files: 148 | dir_name = files[0] 149 | self.cpio.mkdir(dir_name) 150 | for filename in files[1:]: 151 | file_hash = self.add_file(dir_name, filename) 152 | if not file_hash: 153 | fail = True 154 | else: 155 | self.hashes.append(relative(filename) + ": " + file_hash) 156 | 157 | for symlink in self.symlinks: 158 | self.cpio.symlink(*symlink) 159 | for devices in self.devices: 160 | self.cpio.mknod(*devices) 161 | 162 | hash_list = "".join([x + "\n" for x in self.hashes]) 163 | #print(hash_list) 164 | hash_list = hash_list.encode('utf-8') 165 | 166 | if self.add_hashes: 167 | self.cpio.add("/hashes", "hashes", hash_list) 168 | 169 | if fail: 170 | return False 171 | 172 | 173 | mkdir(self.install_dir) 174 | initrd_file = os.path.join(self.install_dir, self.filename) 175 | 176 | info("BUILD " + self.name + ": " + relative(initrd_file)) 177 | 178 | is_compressed = self.filename.endswith('.xz') 179 | image = self.cpio.tobytes(compressed=is_compressed) 180 | writefile(initrd_file, image) 181 | writefile(initrd_file + ".hashes", hash_list) 182 | 183 | writefile(build_canary, b'') 184 | self.built = True 185 | 186 | info("INSTALL " + self.name + ": " + sha256hex(image)) 187 | 188 | return self 189 | 190 | -------------------------------------------------------------------------------- /worldbuilder/linux.py: -------------------------------------------------------------------------------- 1 | # Linux gets its own specialized builder since the kconfig 2 | # setup is a little challenging and there is a need to have headers 3 | # installed separately from the kernel builds. 4 | 5 | from worldbuilder.submodule import Submodule 6 | from worldbuilder.initrd import Initrd 7 | from worldbuilder.util import * 8 | from worldbuilder.commands import prefix_map 9 | 10 | versions = { 11 | "4.14.62": "51ca4d7e8ee156dc0f19bc7768915cfae41dbb0b4f251e4fa8b178c5674c22ab", 12 | "4.19.139": "9c4ebf21fe949f80fbcfbbd6e7fe181040d325e89475e230ab53ef01f9d55605", 13 | "5.4.69": "a8b31d716b397303a183e42ad525ff2871024a43e3ea530d0fdf73b7f9d27da7", 14 | "5.4.117": "4e989b5775830092e5c76b5cca65ebff862ad0c87d0b58c3a20d415c3d4ec770", 15 | } 16 | 17 | def LinuxSrc( 18 | version = "5.4.117", 19 | patches = None, 20 | tarhash = None, 21 | ): 22 | if not tarhash: 23 | if version not in versions: 24 | warn("Linux kernel version " + version + " unknown!") 25 | else: 26 | tarhash = versions[version] 27 | 28 | return Submodule( 29 | 'linux', 30 | url = "https://cdn.kernel.org/pub/linux/kernel/v%(major)s.x/linux-%(version)s.tar.xz", 31 | version = version, 32 | tarhash = tarhash, 33 | patches = patches, 34 | configure = [ 35 | "make", 36 | "-C%(src_dir)s", 37 | "O=%(install_dir)s", 38 | "defconfig", 39 | ], 40 | install = [ 41 | "make", 42 | "-C%(src_dir)s", 43 | "O=%(install_dir)s", 44 | "headers_install" 45 | ], 46 | inc_dir = "usr/include", 47 | ) 48 | 49 | def Linux( 50 | name, 51 | linux_src = None, 52 | depends = None, 53 | compiler = None, 54 | initrd = None, 55 | hostname = None, 56 | config = None, 57 | config_append = None, 58 | cmdline = None, 59 | ): 60 | if not depends: 61 | depends = [] 62 | 63 | # if they didn't say which kernel, use the default 64 | if not linux_src: 65 | linux_src = LinuxSrc() 66 | depends.append(linux_src) 67 | 68 | if type(linux_src) is str: 69 | (linux_name,linux_version) = linux_src.rsplit("-", 1) 70 | else: 71 | linux_version = linux_src.version 72 | linux_name = linux_src.name 73 | 74 | 75 | # The Linux kernel will create an irreproducible initrd 76 | # if one is not specified. This creates a tiny one with 77 | # just the /dev/console required to boot the kernel. 78 | if not initrd: 79 | initrd = Initrd("dev-" + name, 80 | filename = "initrd.cpio", 81 | version = "0.0.0", 82 | add_hashes = False, 83 | devices = [ 84 | [ "/dev/console", "c", 5, 1 ], 85 | ], 86 | ) 87 | initrd_name = "initrd-dev-" + name 88 | elif type(initrd) == str: 89 | initrd_name = initrd 90 | else: 91 | initrd_name = initrd.name 92 | 93 | depends.append(initrd) 94 | 95 | cross_tools_if_cross = [] 96 | if compiler: 97 | depends.append(compiler.crossgcc) 98 | cross_tools_if_cross = [ 99 | *compiler.cross_tools_nocc, 100 | "CROSS_COMPILE=" + compiler.cross, 101 | "CC=" + compiler.cross + "gcc " + prefix_map, 102 | #"LD=" + compiler.cross + "ld --build-id=none", 103 | #+ " -ffile-prefix-map=%(top_dir)s/out=/build" 104 | #+ " -ffile-prefix-map=%(top_dir)s/src=/src" 105 | ] 106 | 107 | if not config_append: 108 | config_append = [] 109 | config_append.append('CONFIG_INITRAMFS_SOURCE="%('+initrd_name+'.install_dir)s/initrd.cpio"') 110 | 111 | if hostname: 112 | config_append.append('CONFIG_DEFAULT_HOSTNAME="' + hostname + '"') 113 | if cmdline: 114 | config_append.append('CONFIG_CMDLINE="' + cmdline + '"') 115 | config_append.append('CONFIG_CMDLINE_BOOL=y') 116 | 117 | return Submodule( 118 | 'linux-' + name, 119 | version = linux_version, 120 | depends = depends, 121 | config_files = [ config ], 122 | config_append = config_append, 123 | configure = [ 124 | "make", 125 | "-C%("+linux_name +".src_dir)s", 126 | "O=%(out_dir)s", 127 | "olddefconfig", 128 | *cross_tools_if_cross, 129 | ], 130 | make = [ 131 | "make", 132 | "-C%("+linux_name+".src_dir)s", 133 | # fake the relative path 134 | #"-C../../../src/"+linux_src.fullname+"/%("+linux_name+".src_hash)s", 135 | "O=%(out_dir)s", 136 | "V=1", 137 | "KBUILD_BUILD_HOST=builder", 138 | "KBUILD_BUILD_USER=%(out_hash)s", 139 | "KBUILD_BUILD_TIMESTAMP=1970-01-01T00:00:00", 140 | "KBUILD_BUILD_VERSION=%("+linux_name+".src_hash)s", 141 | *cross_tools_if_cross, 142 | ], 143 | install = [ 144 | "cp", "arch/x86/boot/bzImage", "%(bin_dir)s", 145 | ], 146 | bin_dir = '', 147 | bins = [ 'bzImage' ], 148 | report_hashes = True, 149 | ) 150 | -------------------------------------------------------------------------------- /worldbuilder/submodule.py: -------------------------------------------------------------------------------- 1 | # Base class for the builders, which can specialize individual functions 2 | # this should be invoked via `make` so that there is a make job server 3 | # available for parallel builds. 4 | # 5 | # downloaded artifacts are placed in build/ftp 6 | # extracted files are in src/short-name/src-hash/ 7 | # build files are in out/short-name/build-hash/ 8 | # 9 | # src-hash is sha256(sha256(file) || sha256(patches...)) 10 | # config-hash is sha256(src-hash || sha256(config...)) 11 | # build-hash is sha256(config-hash || sha256(deps...)) 12 | # 13 | # the merkle tree ensures that the output in the build directory is 14 | # reproducible based on its dependencies (assuming that each source 15 | # has a reproducible build) and the configuration applied to the build. 16 | # 17 | # does this capture the actual build instructions? since the builder can 18 | # change the parameters to `configure` or `make`, the `self.configure` array should 19 | # be captured (before the substitutions) 20 | # 21 | import os 22 | import sys 23 | import requests 24 | from tempfile import NamedTemporaryFile 25 | from glob import glob 26 | 27 | from worldbuilder.util import * 28 | 29 | build_dir = 'build' 30 | ftp_dir = os.path.join(build_dir, 'ftp') 31 | src_dir = os.path.join(build_dir, 'src') 32 | out_dir = os.path.join(build_dir, 'out') 33 | cache_dir = os.path.join(build_dir, 'cache') 34 | install_dir = os.path.join(build_dir, 'install') 35 | cache_server = None 36 | 37 | # global list of modules; names must be unique 38 | global_mods = {} 39 | 40 | class Submodule: 41 | def __init__(self, 42 | name, 43 | url = None, 44 | #git = None, 45 | version = None, 46 | tarhash = None, 47 | patches = None, 48 | patch_dir = None, 49 | dirty = False, 50 | config_files = None, 51 | kconfig_file = ".config", 52 | config_append = None, 53 | configure = None, 54 | make = None, 55 | install = None, 56 | depends = None, 57 | dep_files = None, 58 | #install_dir = "install", 59 | lib_dir = "lib", 60 | bin_dir = "bin", 61 | inc_dir = "include", 62 | patch_level = 1, 63 | strip_components = 1, 64 | bins = None, 65 | libs = None, 66 | report_hashes = False, 67 | cacheable = False, 68 | ): 69 | #if not url and not git: 70 | #raise RuntimeError("url or git must be specified") 71 | if name.endswith("-" + version): 72 | self.fullname = name 73 | else: 74 | self.fullname = name + "-" + version 75 | 76 | if name in global_mods: 77 | info(name + ": already exists in the global module list?") 78 | else: 79 | global_mods[name] = self 80 | global_mods[name + "-" + version] = self 81 | 82 | self.name = name 83 | self.url = url 84 | #self.git = git 85 | self.report_hashes = report_hashes 86 | self.version = "NOVERSION" if not version else version 87 | self.tarhash = tarhash 88 | self.patch_files = patches or [] 89 | self.config_files = config_files or [] 90 | self.config_append = config_append or [] 91 | self.kconfig_file = kconfig_file 92 | 93 | self.configure_commands = configure # or [ "true" ] 94 | self.make_commands = make #or [ "true" ] 95 | self.install_commands = install #or [ "true" ] 96 | self.cacheable = cacheable 97 | 98 | self.depends = depends or [] 99 | self.dep_files = dep_files or [] 100 | self._bin_dir = "bin" if bin_dir is None else bin_dir 101 | self._lib_dir = "lib" if lib_dir is None else lib_dir 102 | self._inc_dir = "include" if inc_dir is None else inc_dir 103 | #self._install_dir = install_dir # "install" if install_dir is None else install_dir 104 | 105 | # referenced to the install directory 106 | # todo: how to handle symlinks? 107 | self._bins = bins or [] 108 | self._libs = libs or [] 109 | self.bins = [] 110 | self.libs = [] 111 | 112 | self.patch_level = patch_level 113 | self.strip_components = strip_components 114 | self.tar_options = [] 115 | self.dirty = dirty 116 | 117 | self.src_hash = zero_hash 118 | self.out_hash = zero_hash 119 | self.tar_file = None 120 | self.major = None 121 | self.minor = None 122 | self.patchver = None 123 | self.src_dir = None 124 | self.out_dir = "/UNINITIALIZED" 125 | self.rout_dir = None 126 | self.install_dir = None 127 | self.bin_dir = None 128 | self.lib_dir = None 129 | self.inc_dir = None 130 | self.top_dir = build_dir 131 | self.last_logfile = "NONE" 132 | 133 | self.fetched = False 134 | self.unpacked = False 135 | self.patched = False 136 | self.configured = False 137 | self.built = False 138 | self.installed = False 139 | self.building = False 140 | 141 | self.ready = False 142 | 143 | # if patch_dir is not None: 144 | # self.patch_files = glob( 145 | 146 | # self.update_dict() 147 | 148 | def state(self): 149 | if not self.ready: 150 | return "NOT READY" 151 | if self.installed: 152 | return "INSTALLED" 153 | if self.built: 154 | return "BUILT " 155 | if self.configured: 156 | return "CONFIGED " 157 | if self.patched: 158 | return "PATCHED " 159 | if self.unpacked: 160 | return "UNPACKED " 161 | if self.fetched: 162 | return "FETCHED " 163 | return "NOSTATE??" 164 | 165 | def format(self, cmd): 166 | try: 167 | return cmd % self.dict 168 | except Exception as e: 169 | print(self.fullname + ":", self.dict) 170 | raise 171 | 172 | def update_dict(self): 173 | # semver the version string 174 | version = self.version.split('.') if self.version else ['0'] 175 | self.major = version[0] 176 | if len(version) > 1: 177 | self.minor = version[1] 178 | if len(version) > 2: 179 | self.patchver = version[2] 180 | 181 | self.dict = { 182 | "version": self.version, 183 | "name": self.name, 184 | "fullname": self.fullname, 185 | "major": self.major, 186 | "minor": self.minor, 187 | "patch": self.patchver, 188 | "tar_file": self.tar_file, 189 | "src_hash": self.src_hash[0:16], 190 | "out_hash": self.out_hash[0:16], 191 | "src_dir": self.src_dir, 192 | "out_dir": self.out_dir, 193 | "rout_dir": self.rout_dir, 194 | "install_dir": self.install_dir, 195 | "lib_dir": self.lib_dir, 196 | "inc_dir": self.inc_dir, 197 | "bin_dir": self.bin_dir, 198 | "top_dir": self.top_dir, 199 | } 200 | 201 | return self.update_dep_dict(self.depends) 202 | 203 | # recursively add the dependency keys 204 | def update_dep_dict(self,deps): 205 | ready = True 206 | for dep in deps: 207 | if type(dep) is str: 208 | # defer this one until later 209 | #print("!!!!!!", self.fullname, "dep ", dep, "not ready") 210 | ready = False 211 | continue 212 | for key in dep.dict: 213 | if key.count('.') != 0: 214 | continue 215 | dep_key = dep.name + "." + key 216 | if dep_key in self.dict: 217 | # this dependency has been processed 218 | # should we warn about a replacement key? 219 | #if self.dict[dep_key] != dep.dict[key]: 220 | # print("------", self.fullname,": ",dep_key,"!=",self.dict[dep_key],dep.dict[key]) 221 | pass 222 | self.dict[dep_key] = dep.dict[key] 223 | # add of of this dependency's dependencies 224 | if not self.update_dep_dict(dep.depends): 225 | ready = False 226 | 227 | return ready 228 | 229 | def get_url(self): 230 | url = self.format(self.url) 231 | (base,f) = os.path.split(url) 232 | return (base+"/" + f, f) 233 | 234 | def fetch(self, force=False, check=False): 235 | if not self.url: 236 | # this is a fake package with no source 237 | self.fetched = True 238 | return self 239 | 240 | (url,tar) = self.get_url() 241 | dest_tar = os.path.abspath(os.path.join(ftp_dir, tar)) 242 | self.tar_file = dest_tar 243 | if exists(dest_tar) and not force: 244 | self.fetched = True 245 | return self 246 | 247 | if check: 248 | return False 249 | 250 | # make sure we have a place to put it 251 | mkdir(ftp_dir) 252 | 253 | info("FETCH " + self.fullname + ": fetching " + url) 254 | 255 | r = requests.get(url) 256 | if r.status_code != requests.codes.ok: 257 | print(url + ": failed!", r.text, file=sys.stderr) 258 | return False 259 | 260 | data = r.content 261 | 262 | if self.tarhash is not None: 263 | data_hash = sha256hex(data) 264 | if data_hash != self.tarhash: 265 | print(tar + ": bad hash! " + data_hash, file=sys.stderr) 266 | writefile(dest_tar + ".bad", data) 267 | return False 268 | #info(tar + ": good hash") 269 | 270 | writefile(dest_tar, data) 271 | self.fetched = True 272 | return self 273 | 274 | def unpack(self, check=False): 275 | if not self.url: 276 | # this is a fake package with no source 277 | self.unpacked = True 278 | return self 279 | 280 | if not self.fetch(check=check): 281 | return False 282 | 283 | unpack_canary = os.path.join(self.src_dir, '.unpacked') 284 | if exists(unpack_canary): 285 | self.unpacked = True 286 | return self 287 | 288 | if check: 289 | return self 290 | 291 | if self.dirty: 292 | info("CLEANUP " + self.fullname) 293 | system("rm", "-rf", self.src_dir) 294 | 295 | mkdir(self.src_dir) 296 | 297 | info("UNPACK " + self.fullname + ": " + relative(self.tar_file) + " -> " + relative(self.src_dir)) 298 | system("tar", 299 | "-xf", self.tar_file, 300 | "-C", self.src_dir, 301 | "--strip-components", "%d" % (self.strip_components), 302 | *self.tar_options, 303 | ) 304 | 305 | writefile(unpack_canary, b'') 306 | self.unpacked = True 307 | return self 308 | 309 | def patch(self, check=False): 310 | if not self.url: 311 | # this is a fake package with no source 312 | if len(self.patch_files) > 0: 313 | self.patched = True 314 | else: 315 | self.unpacked = True 316 | return self 317 | 318 | if not self.unpack(check): 319 | return False 320 | patch_canary = os.path.join(self.src_dir, '.patched') 321 | if exists(patch_canary): 322 | if len(self.patch_files) > 0: 323 | self.patched = True 324 | return self 325 | 326 | if check: 327 | return self 328 | 329 | mkdir(self.out_dir) 330 | 331 | for (patch_file,patch) in self.patches: 332 | info("PATCH " + self.fullname + ": " + relative(patch_file)) 333 | 334 | with NamedTemporaryFile() as tmp: 335 | tmp.write(patch) 336 | tmp.flush() 337 | 338 | system("patch", 339 | "--input", tmp.name, 340 | "--directory", self.src_dir, 341 | "-p%d" % (self.patch_level), 342 | log=os.path.join(self.out_dir, "patch-log") 343 | ) 344 | 345 | writefile(patch_canary, b'') 346 | if len(self.patch_files) > 0: 347 | self.patched = True 348 | return self 349 | 350 | def compute_src_hash(self): 351 | self.src_hash = self.tarhash or zero_hash 352 | 353 | # if the name includes its own version, don't double append it 354 | if self.name.endswith(self.version): 355 | src_subdir = self.name 356 | else: 357 | src_subdir = self.name + "-" + self.version 358 | 359 | if not self.dirty: 360 | # unpack the clean source in its own directory 361 | # for dirty ones the src_dir will be updated based on the 362 | # output hash, computed later 363 | src_subdir = os.path.join(src_subdir, self.src_hash[0:16]) 364 | self.src_dir = os.path.abspath(os.path.join(src_dir, src_subdir)) 365 | 366 | # setup some of our dictionary items 367 | self.update_dict() 368 | 369 | self.patches = [] 370 | for filename in self.patch_files: 371 | expanded = self.format(filename) 372 | files = sorted(glob(expanded)) 373 | if len(files) == 0: 374 | # files are missing! 375 | print(self.fullname + ": no match for " + expanded + "(originally " + filename + ")", file=sys.stderr) 376 | #return False 377 | for patch_filename in files: 378 | patch = readfile(patch_filename) 379 | self.patches.append([patch_filename, patch]) 380 | self.src_hash = extend(self.src_hash, [patch]) 381 | #print(self.name + ": patch file " + patch_filename, self.src_hash) 382 | 383 | def compute_out_hash(self, config_file_hash = zero_hash): 384 | # the output hash depends on the source hash, 385 | # the source config files, any updates to those files, 386 | # the commands executed to configure the programs, 387 | # and any dependencies 388 | # todo: should the hash be on the unexpanded append lines? 389 | self.configs = readfiles(self.config_files) 390 | config_file_hash = extend(config_file_hash, self.configs) 391 | 392 | # hash the unexpanded the configuration appended lines first 393 | for append in self.config_append: 394 | config_file_hash = extend(config_file_hash, append) 395 | 396 | config_hash = zero_hash 397 | if self.configure_commands: 398 | if type(self.configure_commands[0]) == str: 399 | self.configure_commands = [ self.configure_commands ] 400 | for commands in self.configure_commands: 401 | cmd_hash = extend(None, commands) 402 | config_hash = extend(config_hash, cmd_hash) 403 | 404 | config_hash = extend(config_hash, [ 405 | #self._install_dir, 406 | self._inc_dir, 407 | self._lib_dir, 408 | self._bin_dir, 409 | "dirty-tree" if self.dirty else "clean-tree", 410 | *self.dep_files, 411 | *self._bins, 412 | *self._libs 413 | ]) 414 | 415 | make_hash = zero_hash 416 | if self.make_commands: 417 | if type(self.make_commands[0]) == str: 418 | self.make_commands = [ self.make_commands ] 419 | for commands in self.make_commands: 420 | cmd_hash = extend(None, commands) 421 | make_hash = extend(make_hash, cmd_hash) 422 | 423 | install_hash = zero_hash 424 | if self.install_commands: 425 | if type(self.install_commands[0]) == str: 426 | self.install_commands = [ self.install_commands ] 427 | for commands in self.install_commands: 428 | cmd_hash = extend(None, commands) 429 | install_hash = extend(install_hash, cmd_hash) 430 | 431 | new_out_hash = extend(self.src_hash, [config_file_hash, config_hash, make_hash, install_hash]) 432 | 433 | # and the output hash of the direct dependencies 434 | for dep in self.depends: 435 | new_out_hash = extend(new_out_hash, dep.out_hash) 436 | 437 | # print(self.name + ": ", new_out_hash, self.src_hash) 438 | if new_out_hash != self.out_hash and self.out_hash != zero_hash: 439 | print(self.fullname + ": HASH CHANGED ", new_out_hash, self.out_hash) 440 | exit(-1) 441 | self.out_hash = new_out_hash 442 | 443 | # todo: include more configuration in the out_hash (dirty, inc_dir, etc) 444 | if self.name.endswith(self.version): 445 | out_subdir = self.name 446 | else: 447 | out_subdir = self.name + "-" + self.version 448 | 449 | out_subdir = os.path.join(out_subdir, self.out_hash[0:16]) 450 | self.out_dir = os.path.abspath(os.path.join(out_dir, out_subdir)) 451 | self.rout_dir = os.path.join('..', '..', '..', 'out', out_subdir) 452 | self.install_dir = os.path.abspath(os.path.join(install_dir, out_subdir)) 453 | self.bin_dir = os.path.join(self.install_dir, self._bin_dir) 454 | self.lib_dir = os.path.join(self.install_dir, self._lib_dir) 455 | self.inc_dir = os.path.join(self.install_dir, self._inc_dir) 456 | self.top_dir = os.path.abspath(build_dir) 457 | 458 | if self.dirty: 459 | # the src_subdir is based on the output hash, 460 | # not the src hash, since it writes to the directory. 461 | self.src_dir = self.out_dir 462 | 463 | self.update_dict() 464 | 465 | # build the list of output binaries and libraries 466 | self.bins = [self.format("%(bin_dir)s/" + f) for f in self._bins] 467 | self.libs = [self.format("%(lib_dir)s/" + f) for f in self._libs] 468 | 469 | 470 | def run_commands(self, logfile_name, command_list): 471 | self.last_logfile = os.path.join(self.out_dir, logfile_name) 472 | for commands in command_list: 473 | cmds = [] 474 | for cmd in commands: 475 | cmds.append(self.format(cmd)) 476 | 477 | system(*cmds, 478 | cwd=self.out_dir, 479 | log=self.last_logfile, 480 | ) 481 | 482 | def configure(self, check=False): 483 | if not self.patch(check): 484 | return False 485 | 486 | config_canary = os.path.join(self.out_dir, ".configured") 487 | if exists(config_canary): 488 | self.configured = True 489 | return self 490 | 491 | if check: 492 | # don't actually touch anything 493 | return self 494 | 495 | mkdir(self.out_dir) 496 | 497 | kconfig_file = os.path.join(self.out_dir, self.kconfig_file) 498 | 499 | # expand the configuration appended lines now 500 | for append in self.config_append: 501 | #print(self.name + ": adding " + append) 502 | self.configs.append(self.format(append).encode('utf-8')) 503 | 504 | writefile(kconfig_file, b'\n'.join(self.configs)) 505 | 506 | if self.configure_commands: 507 | info("CONFIG " + self.fullname) 508 | self.run_commands("configure-log", self.configure_commands) 509 | 510 | writefile(config_canary, b'') 511 | self.configured = True 512 | return self 513 | 514 | 515 | def build_required(self, force, build_canary): 516 | # update our check time for GC of build trees 517 | mkdir(self.out_dir) 518 | writefile(os.path.join(self.out_dir, '.build-checked'), b'') 519 | 520 | # no canary? definitely have to rebuild 521 | self.built = False 522 | if not exists(build_canary) or force: 523 | return True 524 | 525 | # do a scan of the dependent files for timestamps relative to canary 526 | canary_build_time = os.stat(build_canary).st_mtime 527 | for filename in self.dep_files: 528 | real_filename = self.format(filename) 529 | if not exists(real_filename): 530 | #print(self.name + ": no " + real_filename) 531 | return True 532 | if os.stat(real_filename).st_mtime > canary_build_time: 533 | #print(self.name + ": newer " + real_filename) 534 | return True 535 | 536 | # and check all of our dependencies 537 | for dep in self.depends: 538 | if not dep.installed: 539 | return True 540 | 541 | # we're probably already built 542 | return False 543 | 544 | def build(self, force=False, check=False): 545 | if not self.configure(check=check): 546 | return False 547 | 548 | build_canary = os.path.join(self.out_dir, ".built-" + self.name) 549 | if not self.build_required(force, build_canary): 550 | # we're already done 551 | self.built = True 552 | return self 553 | if check: 554 | return False 555 | 556 | if self.make_commands: 557 | info("BUILD " + self.fullname) 558 | self.run_commands("make-log", self.make_commands) 559 | 560 | writefile(build_canary, b'') 561 | self.built = True 562 | 563 | return self 564 | 565 | def cache_create(self, cache_dir): 566 | mkdir(cache_dir) 567 | cache_filename = self.fullname + "-" + self.out_hash[0:16] + ".tar.gz" 568 | tar_filename = os.path.join(cache_dir, cache_filename) 569 | info("CACHE " + self.fullname + ": " + relative(tar_filename)) 570 | system("tar", "-zcf", tar_filename, "-C", self.install_dir, ".") 571 | return True 572 | 573 | def cache_fetch(self): 574 | cache_filename = self.fullname + "-" + self.out_hash[0:16] + ".tar.gz" 575 | tar_filename = os.path.join(cache_dir, cache_filename) 576 | url = cache_server + "/" + cache_filename 577 | r = requests.get(url) 578 | if r.status_code != requests.codes.ok: 579 | return False 580 | 581 | mkdir(cache_dir) 582 | mkdir(self.install_dir) 583 | 584 | info("CACHED " + self.fullname + ": " + url) 585 | writefile(tar_filename, r.content) 586 | system("tar", "-zxf", tar_filename, "-C", self.install_dir) 587 | 588 | return True 589 | 590 | def install(self, force=False, check=False): 591 | cache_canary = os.path.join(self.install_dir, ".cache-" + self.name) 592 | if exists(cache_canary) and not force: 593 | # this is a cached build, do not attempt any further builds 594 | #print(self.name + ": cached build available " + self.install_dir) 595 | self.installed = True 596 | return self 597 | 598 | # if we're actually building and cacheable, try to see if the 599 | # cache server has a cached version for us 600 | if self.cacheable and cache_server and not check: 601 | if self.cache_fetch() and exists(cache_canary): 602 | return True 603 | 604 | if not self.build(force=force, check=check): 605 | return False 606 | 607 | install_canary = os.path.join(self.install_dir, ".install-" + self.name) 608 | if exists(install_canary) and not force: 609 | self.installed = True 610 | return self 611 | if check: 612 | return self 613 | 614 | mkdir(self.install_dir) 615 | 616 | if self.install_commands: 617 | info("INSTALL " + self.fullname + ": " + relative(self.install_dir) ) 618 | self.run_commands("install-log", self.install_commands) 619 | 620 | if self.report_hashes: 621 | for filename in self.bins: 622 | full_name = os.path.join(self.bin_dir, filename) 623 | file_hash = sha256hex(readfile(full_name)) 624 | print(relative(full_name) + ": " + file_hash) 625 | for filename in self.libs: 626 | full_name = os.path.join(self.bin_dir, filename) 627 | file_hash = sha256hex(readfile(full_name)) 628 | print(relative(full_name) + ": " + file_hash) 629 | 630 | writefile(install_canary, b'') 631 | self.installed = True 632 | 633 | if self.cacheable: 634 | writefile(cache_canary, b'') 635 | 636 | return self 637 | 638 | def update_hashes(self): 639 | self.compute_src_hash() 640 | self.compute_out_hash() 641 | self.ready = True 642 | -------------------------------------------------------------------------------- /worldbuilder/util.py: -------------------------------------------------------------------------------- 1 | # utility functions for the worldbuilder classes 2 | import os 3 | import sys 4 | import requests 5 | import hashlib 6 | import subprocess 7 | import traceback 8 | import time 9 | from shlex import quote 10 | 11 | def now(): 12 | return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 13 | 14 | zero_hash = '0' * 64 15 | verbose = 1 16 | 17 | def sha256hex(data): 18 | #print("hashing %d bytes" % (len(data)), data) 19 | if type(data) is str: 20 | data = data.encode('utf-8') 21 | return hashlib.sha256(data).hexdigest() 22 | 23 | def extend(h, data): 24 | if h is None: 25 | h = zero_hash 26 | for datum in data: 27 | h = sha256hex(h + sha256hex(datum)) 28 | return h 29 | 30 | def system(*s, cwd=None, log=None): 31 | if not cwd: 32 | cwd = '.' 33 | if verbose > 2: 34 | print(cwd, s) 35 | 36 | if log: 37 | logfile = open(log, "a+") 38 | print("----- " + now() + " -----", file=logfile) 39 | print("cd " + os.path.abspath(cwd), file=logfile) 40 | print(*s, file=logfile) 41 | logfile.flush() 42 | else: 43 | logfile = None 44 | 45 | # do not close file descriptors, which will allow 46 | # communication from sub-make invocations to the make 47 | # that invoked us 48 | subprocess.run(s, cwd=cwd, check=True, close_fds=False, stdout=logfile, stderr=logfile) 49 | if logfile: 50 | logfile.close() 51 | 52 | def die(*s): 53 | print(now(), *s, file=sys.stderr) 54 | exit(1) 55 | 56 | def info(*s): 57 | if verbose > 0: 58 | print(now(), *s) 59 | sys.stdout.flush() 60 | 61 | def exists(*paths): 62 | try: 63 | os.stat(os.path.join(*paths)) 64 | return True 65 | except Exception as e: 66 | return False 67 | 68 | def mkdir(d): 69 | os.makedirs(d, exist_ok=True) 70 | 71 | def writefile(name, data): 72 | with open(name, "wb") as f: 73 | f.write(data) 74 | 75 | def readfile(name): 76 | with open(name, "rb") as f: 77 | return f.read() 78 | 79 | def readfiles(names): 80 | d = [] 81 | for name in names: 82 | d.append(readfile(name)) 83 | return d 84 | 85 | def relative(dirname): 86 | #abs_build = os.path.abspath(build_dir) 87 | return os.path.relpath(dirname) 88 | 89 | def make_env(vars): 90 | outvars=[] 91 | for v in vars: 92 | (name,val) = v.split("=",1) 93 | outvars.append(name + "=" + quote(val)) 94 | return outvars 95 | 96 | --------------------------------------------------------------------------------