137 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { lib, config, ... }:
 | |
| 
 | |
| with lib;
 | |
| let
 | |
|   findWinner = candidates: winner:
 | |
|     any (x: x == winner) candidates;
 | |
| 
 | |
|   # winners is an ordered list where first item wins over 2nd etc
 | |
|   mergeAnswer = winners: locs: defs:
 | |
|     let
 | |
|       values = map (x: x.value) defs;
 | |
|       inter = intersectLists values winners;
 | |
|       winner = head winners;
 | |
|     in
 | |
|     if defs == [] then abort "This case should never happen."
 | |
|     else if winner == [] then abort "Give a valid list of winner"
 | |
|     else if inter == [] then mergeOneOption locs defs
 | |
|     else if findWinner values winner then
 | |
|       winner
 | |
|     else
 | |
|       mergeAnswer (tail winners) locs defs;
 | |
| 
 | |
|   mergeFalseByDefault = locs: defs:
 | |
|     if defs == [] then abort "This case should never happen."
 | |
|     else if any (x: x == false) defs then false
 | |
|     else true;
 | |
| 
 | |
|   kernelItem = types.submodule {
 | |
|     options = {
 | |
|       tristate = mkOption {
 | |
|         type = types.enum [ "y" "m" "n" null ] // {
 | |
|           merge = mergeAnswer [ "y" "m" "n" ];
 | |
|         };
 | |
|         default = null;
 | |
|         internal = true;
 | |
|         visible = true;
 | |
|         description = ''
 | |
|           Use this field for tristate kernel options expecting a "y" or "m" or "n".
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       freeform = mkOption {
 | |
|         type = types.nullOr types.str // {
 | |
|           merge = mergeEqualOption;
 | |
|         };
 | |
|         default = null;
 | |
|         example = ''MMC_BLOCK_MINORS.freeform = "32";'';
 | |
|         description = ''
 | |
|           Freeform description of a kernel configuration item value.
 | |
|         '';
 | |
|       };
 | |
| 
 | |
|       optional = mkOption {
 | |
|         type = types.bool // { merge = mergeFalseByDefault; };
 | |
|         default = false;
 | |
|         description = ''
 | |
|           Wether option should generate a failure when unused.
 | |
|         '';
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   mkValue = with lib; val:
 | |
|   let
 | |
|     isNumber = c: elem c ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9"];
 | |
| 
 | |
|   in
 | |
|     if (val == "") then "\"\""
 | |
|     else if val == "y" || val == "m" || val == "n" then val
 | |
|     else if all isNumber (stringToCharacters val) then val
 | |
|     else if substring 0 2 val == "0x" then val
 | |
|     else val; # FIXME: fix quoting one day
 | |
| 
 | |
| 
 | |
|   # generate nix intermediate kernel config file of the form
 | |
|   #
 | |
|   #       VIRTIO_MMIO m
 | |
|   #       VIRTIO_BLK y
 | |
|   #       VIRTIO_CONSOLE n
 | |
|   #       NET_9P_VIRTIO? y
 | |
|   #
 | |
|   # Borrowed from copumpkin https://github.com/NixOS/nixpkgs/pull/12158
 | |
|   # returns a string, expr should be an attribute set
 | |
|   # Use mkValuePreprocess to preprocess option values, aka mark 'modules' as 'yes' or vice-versa
 | |
|   # use the identity if you don't want to override the configured values
 | |
|   generateNixKConf = exprs:
 | |
|   let
 | |
|     mkConfigLine = key: item:
 | |
|       let
 | |
|         val = if item.freeform != null then item.freeform else item.tristate;
 | |
|       in
 | |
|         if val == null
 | |
|           then ""
 | |
|           else if (item.optional)
 | |
|             then "${key}? ${mkValue val}\n"
 | |
|             else "${key} ${mkValue val}\n";
 | |
| 
 | |
|     mkConf = cfg: concatStrings (mapAttrsToList mkConfigLine cfg);
 | |
|   in mkConf exprs;
 | |
| 
 | |
| in
 | |
| {
 | |
| 
 | |
|   options = {
 | |
| 
 | |
|     intermediateNixConfig = mkOption {
 | |
|       readOnly = true;
 | |
|       type = types.lines;
 | |
|       example = ''
 | |
|         USB? y
 | |
|         DEBUG n
 | |
|       '';
 | |
|       description = ''
 | |
|         The result of converting the structured kernel configuration in settings
 | |
|         to an intermediate string that can be parsed by generate-config.pl to
 | |
|         answer the kernel `make defconfig`.
 | |
|       '';
 | |
|     };
 | |
| 
 | |
|     settings = mkOption {
 | |
|       type = types.attrsOf kernelItem;
 | |
|       example = literalExample '' with lib.kernel; {
 | |
|         "9P_NET" = yes;
 | |
|         USB = optional yes;
 | |
|         MMC_BLOCK_MINORS = freeform "32";
 | |
|       }'';
 | |
|       description = ''
 | |
|         Structured kernel configuration.
 | |
|       '';
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   config = {
 | |
|     intermediateNixConfig = generateNixKConf config.settings;
 | |
|   };
 | |
| }
 | 
