mtdimage.nix (3895B)
1 { 2 config 3 , pkgs 4 , lib 5 , ... 6 }: 7 let 8 inherit (lib) mkOption types concatStringsSep; 9 inherit (config.boot) tftp; 10 in { 11 options.system.outputs = { 12 firmware = mkOption { 13 type = types.package; 14 internal = true; # component of mtdimage 15 description = '' 16 Binary image (combining kernel, FDT, rootfs, initramfs 17 if needed, etc) for the target device. 18 ''; 19 }; 20 flash-scr = mkOption { 21 type = types.package; 22 internal = true; # component of mtdimage 23 description = '' 24 Copy-pastable U-Boot commands to TFTP download the 25 image and write it to flash 26 ''; 27 }; 28 mtdimage = mkOption { 29 type = types.package; 30 description = '' 31 mtdimage 32 ********** 33 34 This creates an image called :file:`firmware.bin` suitable for 35 squashfs or jffs2 systems. It can be flashed from U-Boot (if 36 you have a serial console connection), or on some devices from 37 the vendor firmware, or from a Liminix kexecboot system. 38 39 If you are flashing from U-Boot, the file 40 :file:`flash.scr` is a sequence of commands 41 which you can paste at the U-Boot prompt to 42 to transfer the firmware file from a TFTP server and 43 write it to flash. **Please read the script before 44 running it: flash operations carry the potential to 45 brick your device** 46 47 .. NOTE:: 48 49 TTL serial connections typically have no form of flow 50 control and so don't always like having massive chunks of 51 text pasted into them - and U-Boot may drop characters 52 while it's busy. So don't necessarily expect to copy-paste 53 the whole of :file:`flash.scr` into a terminal emulator and 54 have it work just like that. You may need to paste each 55 line one at a time, or even retype it. 56 ''; 57 }; 58 }; 59 60 config = { 61 kernel = { 62 config = { 63 MTD_SPLIT_UIMAGE_FW = "y"; 64 } // lib.optionalAttrs (pkgs.stdenv.isMips) { 65 # https://stackoverflow.com/questions/26466470/can-the-logical-erase-block-size-of-an-mtd-device-be-increased 66 MTD_SPI_NOR_USE_4K_SECTORS = "n"; 67 }; 68 }; 69 70 programs.busybox.applets = [ 71 "flashcp" 72 ]; 73 74 system.outputs = { 75 firmware = 76 let 77 o = config.system.outputs; 78 bs = toString config.hardware.flash.eraseBlockSize; 79 in pkgs.runCommand "firmware" {} '' 80 dd if=${o.uimage} of=$out bs=${bs} conv=sync 81 dd if=${o.rootfs} of=$out bs=${bs} conv=sync,nocreat,notrunc oflag=append 82 ''; 83 mtdimage = 84 let o = config.system.outputs; in 85 # could use trivial-builders.linkFarmFromDrvs here? 86 pkgs.runCommand "mtdimage" {} '' 87 mkdir $out 88 cd $out 89 ln -s ${o.firmware} firmware.bin 90 ln -s ${o.rootfs} rootfs 91 ln -s ${o.kernel} vmlinux 92 ln -s ${o.manifest} manifest 93 ln -s ${o.kernel.headers} build 94 ln -s ${o.uimage} uimage 95 ln -s ${o.dtb} dtb 96 ln -s ${o.flash-scr} flash.scr 97 ''; 98 99 flash-scr = 100 let 101 inherit (pkgs.lib.trivial) toHexString; 102 inherit (config.hardware) flash; 103 in 104 pkgs.buildPackages.runCommand "" {} '' 105 imageSize=$(stat -L -c %s ${config.system.outputs.firmware}) 106 cat > $out << EOF 107 setenv serverip ${tftp.serverip} 108 setenv ipaddr ${tftp.ipaddr} 109 tftp 0x${toHexString tftp.loadAddress} result/firmware.bin 110 erase 0x${toHexString flash.address} +0x${toHexString flash.size} 111 cp.b 0x${toHexString tftp.loadAddress} 0x${toHexString flash.address} \''${filesize} 112 echo command line was ${builtins.toJSON (concatStringsSep " " config.boot.commandLine)} 113 EOF 114 ''; 115 }; 116 }; 117 }