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