2019-09-04 07:49:13 +03:00
|
|
|
{ lib, imageBuilder, dosfstools, mtools, libfaketime}:
|
2019-08-27 21:14:57 +03:00
|
|
|
|
|
|
|
/* */ let scope = { "fileSystem.makeFAT32" =
|
|
|
|
|
2019-08-31 05:43:30 +03:00
|
|
|
let
|
2019-09-04 07:49:13 +03:00
|
|
|
inherit (lib.strings) splitString;
|
2019-08-31 05:43:30 +03:00
|
|
|
inherit (imageBuilder) makeFilesystem;
|
2019-09-04 07:49:13 +03:00
|
|
|
# The default from `mkfs.fat`.
|
|
|
|
reservedSectors = 32;
|
|
|
|
# The default from `mkfs.fat`.
|
|
|
|
hiddenSectors = 0;
|
|
|
|
|
|
|
|
# The default from `mkfs.fat`.
|
|
|
|
numberOfFats = 2;
|
|
|
|
# Extra padding per FAT, a constant in code
|
|
|
|
fatPadding = 4;
|
|
|
|
|
|
|
|
# I have not been able to validate that it could be different from 1 for FAT32.
|
|
|
|
# It seems the different values (e.g. 4) are for FAT12 and FAT16.
|
|
|
|
# This is the only "bad" assumption here.
|
|
|
|
clusterSize = 1;
|
|
|
|
|
|
|
|
# Bash doesn't do floating point representations. Multiplications and divisions
|
|
|
|
# are handled with enough precision that we can multiply and divide to get a precision.
|
|
|
|
precision = 1000;
|
|
|
|
|
|
|
|
first = list: lib.lists.last (lib.lists.reverseList list);
|
|
|
|
chopDecimal = f: first (splitString "." (toString f));
|
2019-08-31 05:43:30 +03:00
|
|
|
in
|
2019-09-02 23:33:21 +03:00
|
|
|
{ partitionID
|
|
|
|
# These defaults are assuming small~ish FAT32 filesystems are generated.
|
|
|
|
, blockSize ? 512
|
|
|
|
, sectorSize ? 512
|
|
|
|
, ... } @ args:
|
2019-08-29 03:50:28 +03:00
|
|
|
makeFilesystem (args // {
|
2019-08-27 21:14:57 +03:00
|
|
|
# FAT32 can be used for ESP. Let's make this obvious.
|
|
|
|
filesystemType = if args ? filesystemType then args.filesystemType else "FAT32";
|
|
|
|
|
2019-09-04 07:49:13 +03:00
|
|
|
inherit blockSize sectorSize;
|
2019-08-31 05:43:30 +03:00
|
|
|
minimumSize = imageBuilder.size.KiB 500;
|
2019-08-29 04:54:12 +03:00
|
|
|
|
2019-08-27 21:14:57 +03:00
|
|
|
nativeBuildInputs = [
|
|
|
|
libfaketime
|
|
|
|
dosfstools
|
|
|
|
mtools
|
|
|
|
];
|
|
|
|
|
2019-09-04 07:49:13 +03:00
|
|
|
computeMinimalSize = ''
|
|
|
|
# `local size` is in bytes.
|
|
|
|
|
|
|
|
# This amount is a static amount of reserved space.
|
|
|
|
local static_reserved=${toString ( (reservedSectors + hiddenSectors) * sectorSize )}
|
|
|
|
|
|
|
|
# This is a constant representing the relative reserved space ratio.
|
|
|
|
local relative_reserved=${
|
|
|
|
chopDecimal (
|
|
|
|
precision - (
|
|
|
|
1.0 * sectorSize / ((clusterSize * sectorSize) + (numberOfFats * fatPadding))
|
|
|
|
# ^ forces floating point
|
|
|
|
) * precision
|
|
|
|
)
|
|
|
|
}
|
|
|
|
# Rounds up the likely truncated result. At worst it's a bit more space.
|
|
|
|
(( relative_reserved++ ))
|
|
|
|
|
|
|
|
echo "static_reserved=$static_reserved" 1>&2
|
|
|
|
echo "relative_reserved=$relative_reserved" 1>&2
|
|
|
|
|
|
|
|
local reservedSize=$(( (static_reserved + size) * relative_reserved / ${toString precision} + static_reserved ))
|
|
|
|
|
|
|
|
echo -n "Adding reservedSize: $size + $reservedSize = " 1>&2
|
|
|
|
size=$((size + reservedSize))
|
|
|
|
echo "$size" 1>&2
|
|
|
|
'';
|
|
|
|
|
2019-08-27 21:14:57 +03:00
|
|
|
filesystemPhase = ''
|
2019-09-01 01:06:12 +03:00
|
|
|
faketime -f "1970-01-01 00:00:00" mkfs.vfat \
|
2019-09-04 07:49:13 +03:00
|
|
|
-R ${toString reservedSectors} \
|
|
|
|
-h ${toString hiddenSectors} \
|
2019-09-02 23:33:21 +03:00
|
|
|
-s ${toString (blockSize / sectorSize)} \
|
|
|
|
-S ${toString sectorSize} \
|
2019-08-27 21:14:57 +03:00
|
|
|
-i $partitionID \
|
|
|
|
-n $partName \
|
|
|
|
"$img"
|
|
|
|
'';
|
|
|
|
|
|
|
|
copyPhase = ''
|
2019-08-29 04:31:45 +03:00
|
|
|
for f in ./* ./.*; do
|
|
|
|
if [[ "$f" != "./." && "$f" != "./.." ]]; then
|
2019-09-01 01:06:12 +03:00
|
|
|
faketime -f "1970-01-01 00:00:00" \
|
2019-08-29 04:47:40 +03:00
|
|
|
mcopy -psv -i "$img" "$f" ::
|
2019-08-29 04:31:45 +03:00
|
|
|
fi
|
|
|
|
done
|
2019-08-27 21:14:57 +03:00
|
|
|
'';
|
|
|
|
|
|
|
|
checkPhase = ''
|
|
|
|
# Always verify FS
|
|
|
|
fsck.vfat -vn "$img"
|
|
|
|
'';
|
|
|
|
})
|
|
|
|
|
|
|
|
/* */ ;}; in scope."fileSystem.makeFAT32"
|