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