1package fsgen 2 3import ( 4 "android/soong/android" 5 "android/soong/filesystem" 6 "fmt" 7 "path/filepath" 8 "strconv" 9 "strings" 10 11 "github.com/google/blueprint/proptools" 12) 13 14func createBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool { 15 partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 16 17 if partitionVariables.TargetKernelPath == "" { 18 // There are potentially code paths that don't set TARGET_KERNEL_PATH 19 return false 20 } 21 22 kernelDir := filepath.Dir(partitionVariables.TargetKernelPath) 23 kernelBase := filepath.Base(partitionVariables.TargetKernelPath) 24 kernelFilegroupName := generatedModuleName(ctx.Config(), "kernel") 25 26 ctx.CreateModuleInDirectory( 27 android.FileGroupFactory, 28 kernelDir, 29 &struct { 30 Name *string 31 Srcs []string 32 Visibility []string 33 }{ 34 Name: proptools.StringPtr(kernelFilegroupName), 35 Srcs: []string{kernelBase}, 36 Visibility: []string{"//visibility:public"}, 37 }, 38 ) 39 40 var partitionSize *int64 41 if partitionVariables.BoardBootimagePartitionSize != "" { 42 // Base of zero will allow base 10 or base 16 if starting with 0x 43 parsed, err := strconv.ParseInt(partitionVariables.BoardBootimagePartitionSize, 0, 64) 44 if err != nil { 45 panic(fmt.Sprintf("BOARD_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardBootimagePartitionSize)) 46 } 47 partitionSize = &parsed 48 } 49 50 var securityPatch *string 51 if partitionVariables.BootSecurityPatch != "" { 52 securityPatch = &partitionVariables.BootSecurityPatch 53 } 54 55 avbInfo := getAvbInfo(ctx.Config(), "boot") 56 57 bootImageName := generatedModuleNameForPartition(ctx.Config(), "boot") 58 59 var dtbPrebuilt *string 60 if dtbImg.include && dtbImg.imgType == "boot" { 61 dtbPrebuilt = proptools.StringPtr(":" + dtbImg.name) 62 } 63 64 var cmdline []string 65 if !buildingVendorBootImage(partitionVariables) { 66 cmdline = partitionVariables.InternalKernelCmdline 67 } 68 69 ctx.CreateModule( 70 filesystem.BootimgFactory, 71 &filesystem.BootimgProperties{ 72 Kernel_prebuilt: proptools.StringPtr(":" + kernelFilegroupName), 73 Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), 74 Partition_size: partitionSize, 75 Use_avb: avbInfo.avbEnable, 76 Avb_mode: avbInfo.avbMode, 77 Avb_private_key: avbInfo.avbkeyFilegroup, 78 Avb_rollback_index: avbInfo.avbRollbackIndex, 79 Avb_algorithm: avbInfo.avbAlgorithm, 80 Security_patch: securityPatch, 81 Dtb_prebuilt: dtbPrebuilt, 82 Cmdline: cmdline, 83 }, 84 &struct { 85 Name *string 86 }{ 87 Name: proptools.StringPtr(bootImageName), 88 }, 89 ) 90 return true 91} 92 93func createVendorBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool { 94 partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 95 96 bootImageName := generatedModuleNameForPartition(ctx.Config(), "vendor_boot") 97 98 avbInfo := getAvbInfo(ctx.Config(), "vendor_boot") 99 100 var dtbPrebuilt *string 101 if dtbImg.include && dtbImg.imgType == "vendor_boot" { 102 dtbPrebuilt = proptools.StringPtr(":" + dtbImg.name) 103 } 104 105 cmdline := partitionVariables.InternalKernelCmdline 106 107 var vendorBootConfigImg *string 108 if name, ok := createVendorBootConfigImg(ctx); ok { 109 vendorBootConfigImg = proptools.StringPtr(":" + name) 110 } 111 112 ctx.CreateModule( 113 filesystem.BootimgFactory, 114 &filesystem.BootimgProperties{ 115 Boot_image_type: proptools.StringPtr("vendor_boot"), 116 Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")), 117 Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), 118 Use_avb: avbInfo.avbEnable, 119 Avb_mode: avbInfo.avbMode, 120 Avb_private_key: avbInfo.avbkeyFilegroup, 121 Avb_rollback_index: avbInfo.avbRollbackIndex, 122 Avb_algorithm: avbInfo.avbAlgorithm, 123 Dtb_prebuilt: dtbPrebuilt, 124 Cmdline: cmdline, 125 Bootconfig: vendorBootConfigImg, 126 }, 127 &struct { 128 Name *string 129 }{ 130 Name: proptools.StringPtr(bootImageName), 131 }, 132 ) 133 return true 134} 135 136func createInitBootImage(ctx android.LoadHookContext) bool { 137 partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 138 139 bootImageName := generatedModuleNameForPartition(ctx.Config(), "init_boot") 140 141 var securityPatch *string 142 if partitionVariables.InitBootSecurityPatch != "" { 143 securityPatch = &partitionVariables.InitBootSecurityPatch 144 } else if partitionVariables.BootSecurityPatch != "" { 145 securityPatch = &partitionVariables.BootSecurityPatch 146 } 147 148 var partitionSize *int64 149 if partitionVariables.BoardInitBootimagePartitionSize != "" { 150 // Base of zero will allow base 10 or base 16 if starting with 0x 151 parsed, err := strconv.ParseInt(partitionVariables.BoardInitBootimagePartitionSize, 0, 64) 152 if err != nil { 153 panic(fmt.Sprintf("BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardInitBootimagePartitionSize)) 154 } 155 partitionSize = &parsed 156 } 157 158 avbInfo := getAvbInfo(ctx.Config(), "init_boot") 159 160 ctx.CreateModule( 161 filesystem.BootimgFactory, 162 &filesystem.BootimgProperties{ 163 Boot_image_type: proptools.StringPtr("init_boot"), 164 Ramdisk_module: proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")), 165 Header_version: proptools.StringPtr(partitionVariables.BoardBootHeaderVersion), 166 Security_patch: securityPatch, 167 Partition_size: partitionSize, 168 Use_avb: avbInfo.avbEnable, 169 Avb_mode: avbInfo.avbMode, 170 Avb_private_key: avbInfo.avbkeyFilegroup, 171 Avb_rollback_index: avbInfo.avbRollbackIndex, 172 Avb_algorithm: avbInfo.avbAlgorithm, 173 }, 174 &struct { 175 Name *string 176 }{ 177 Name: proptools.StringPtr(bootImageName), 178 }, 179 ) 180 return true 181} 182 183// Returns the equivalent of the BUILDING_BOOT_IMAGE variable in make. Derived from this logic: 184// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=458;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 185func buildingBootImage(partitionVars android.PartitionVariables) bool { 186 if partitionVars.BoardUsesRecoveryAsBoot { 187 return false 188 } 189 190 if partitionVars.ProductBuildBootImage { 191 return true 192 } 193 194 if len(partitionVars.BoardPrebuiltBootimage) > 0 { 195 return false 196 } 197 198 if len(partitionVars.BoardBootimagePartitionSize) > 0 { 199 return true 200 } 201 202 // TODO: return true if BOARD_KERNEL_BINARIES is set and has a *_BOOTIMAGE_PARTITION_SIZE 203 // variable. However, I don't think BOARD_KERNEL_BINARIES is ever set in practice. 204 205 return false 206} 207 208// Returns the equivalent of the BUILDING_VENDOR_BOOT_IMAGE variable in make. Derived from this logic: 209// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=518;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 210func buildingVendorBootImage(partitionVars android.PartitionVariables) bool { 211 if v, exists := boardBootHeaderVersion(partitionVars); exists && v >= 3 { 212 x := partitionVars.ProductBuildVendorBootImage 213 if x == "" || x == "true" { 214 return true 215 } 216 } 217 218 return false 219} 220 221// Derived from: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=480;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0 222func buildingInitBootImage(partitionVars android.PartitionVariables) bool { 223 if !partitionVars.ProductBuildInitBootImage { 224 if partitionVars.BoardUsesRecoveryAsBoot || len(partitionVars.BoardPrebuiltInitBootimage) > 0 { 225 return false 226 } else if len(partitionVars.BoardInitBootimagePartitionSize) > 0 { 227 return true 228 } 229 } else { 230 if partitionVars.BoardUsesRecoveryAsBoot { 231 panic("PRODUCT_BUILD_INIT_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT. Use only one option.") 232 } 233 return true 234 } 235 return false 236} 237 238func boardBootHeaderVersion(partitionVars android.PartitionVariables) (int, bool) { 239 if len(partitionVars.BoardBootHeaderVersion) == 0 { 240 return 0, false 241 } 242 v, err := strconv.ParseInt(partitionVars.BoardBootHeaderVersion, 10, 32) 243 if err != nil { 244 panic(fmt.Sprintf("BOARD_BOOT_HEADER_VERSION must be an int, got: %q", partitionVars.BoardBootHeaderVersion)) 245 } 246 return int(v), true 247} 248 249type dtbImg struct { 250 // whether to include the dtb image in boot image 251 include bool 252 253 // name of the generated dtb image filegroup name 254 name string 255 256 // type of the boot image that the dtb image argument should be specified 257 imgType string 258} 259 260func createDtbImgFilegroup(ctx android.LoadHookContext) dtbImg { 261 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 262 if !partitionVars.BoardIncludeDtbInBootimg { 263 return dtbImg{include: false} 264 } 265 for _, copyFilePair := range partitionVars.ProductCopyFiles { 266 srcDestList := strings.Split(copyFilePair, ":") 267 if len(srcDestList) < 2 { 268 ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair) 269 } 270 if srcDestList[1] == "dtb.img" { 271 moduleName := generatedModuleName(ctx.Config(), "dtb_img_filegroup") 272 ctx.CreateModuleInDirectory( 273 android.FileGroupFactory, 274 filepath.Dir(srcDestList[0]), 275 &struct { 276 Name *string 277 Srcs []string 278 }{ 279 Name: proptools.StringPtr(moduleName), 280 Srcs: []string{filepath.Base(srcDestList[1])}, 281 }, 282 ) 283 imgType := "vendor_boot" 284 if !buildingVendorBootImage(partitionVars) { 285 imgType = "boot" 286 } 287 return dtbImg{include: true, name: moduleName, imgType: imgType} 288 } 289 } 290 return dtbImg{include: false} 291} 292 293func createVendorBootConfigImg(ctx android.LoadHookContext) (string, bool) { 294 partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse 295 bootconfig := partitionVars.InternalBootconfig 296 bootconfigFile := partitionVars.InternalBootconfigFile 297 if len(bootconfig) == 0 && len(bootconfigFile) == 0 { 298 return "", false 299 } 300 301 vendorBootconfigImgModuleName := generatedModuleName(ctx.Config(), "vendor_bootconfig_image") 302 303 ctx.CreateModule( 304 filesystem.BootconfigModuleFactory, 305 &struct { 306 Name *string 307 Boot_config []string 308 Boot_config_file *string 309 }{ 310 Name: proptools.StringPtr(vendorBootconfigImgModuleName), 311 Boot_config: bootconfig, 312 Boot_config_file: proptools.StringPtr(bootconfigFile), 313 }, 314 ) 315 316 return vendorBootconfigImgModuleName, true 317} 318