1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2022 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage filesystem 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "strconv" 20*333d2b36SAndroid Build Coastguard Worker 21*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 24*333d2b36SAndroid Build Coastguard Worker) 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Workertype avbAddHashFooter struct { 27*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 28*333d2b36SAndroid Build Coastguard Worker android.DefaultableModuleBase 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker properties avbAddHashFooterProperties 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Worker output android.Path 33*333d2b36SAndroid Build Coastguard Worker installDir android.InstallPath 34*333d2b36SAndroid Build Coastguard Worker} 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workertype avbProp struct { 37*333d2b36SAndroid Build Coastguard Worker // Name of a property 38*333d2b36SAndroid Build Coastguard Worker Name *string 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Worker // Value of a property. Can't be used together with `file`. 41*333d2b36SAndroid Build Coastguard Worker Value *string 42*333d2b36SAndroid Build Coastguard Worker 43*333d2b36SAndroid Build Coastguard Worker // File from which the value of the prop is read from. Can't be used together with `value`. 44*333d2b36SAndroid Build Coastguard Worker File *string `android:"path,arch_variant"` 45*333d2b36SAndroid Build Coastguard Worker} 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Workertype avbAddHashFooterProperties struct { 48*333d2b36SAndroid Build Coastguard Worker // Source file of this image. Can reference a genrule type module with the ":module" syntax. 49*333d2b36SAndroid Build Coastguard Worker Src *string `android:"path,arch_variant"` 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker // Set the name of the output. Defaults to <module_name>.img. 52*333d2b36SAndroid Build Coastguard Worker Filename *string 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Worker // Name of the image partition. Defaults to the name of this module. 55*333d2b36SAndroid Build Coastguard Worker Partition_name *string 56*333d2b36SAndroid Build Coastguard Worker 57*333d2b36SAndroid Build Coastguard Worker // Size of the partition. Defaults to dynamically calculating the size. 58*333d2b36SAndroid Build Coastguard Worker Partition_size *int64 59*333d2b36SAndroid Build Coastguard Worker 60*333d2b36SAndroid Build Coastguard Worker // Path to the private key that avbtool will use to sign this image. 61*333d2b36SAndroid Build Coastguard Worker Private_key *string `android:"path"` 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Worker // Algorithm that avbtool will use to sign this image. Default is SHA256_RSA4096. 64*333d2b36SAndroid Build Coastguard Worker Algorithm *string 65*333d2b36SAndroid Build Coastguard Worker 66*333d2b36SAndroid Build Coastguard Worker // The salt in hex. Required for reproducible builds. 67*333d2b36SAndroid Build Coastguard Worker Salt *string 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Worker // List of properties to add to the footer 70*333d2b36SAndroid Build Coastguard Worker Props []avbProp 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Worker // The index used to prevent rollback of the image on device. 73*333d2b36SAndroid Build Coastguard Worker Rollback_index *int64 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Worker // Include descriptors from images 76*333d2b36SAndroid Build Coastguard Worker Include_descriptors_from_images []string `android:"path,arch_variant"` 77*333d2b36SAndroid Build Coastguard Worker} 78*333d2b36SAndroid Build Coastguard Worker 79*333d2b36SAndroid Build Coastguard Worker// The AVB footer adds verification information to the image. 80*333d2b36SAndroid Build Coastguard Workerfunc avbAddHashFooterFactory() android.Module { 81*333d2b36SAndroid Build Coastguard Worker module := &avbAddHashFooter{} 82*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&module.properties) 83*333d2b36SAndroid Build Coastguard Worker android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) 84*333d2b36SAndroid Build Coastguard Worker android.InitDefaultableModule(module) 85*333d2b36SAndroid Build Coastguard Worker return module 86*333d2b36SAndroid Build Coastguard Worker} 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) installFileName() string { 89*333d2b36SAndroid Build Coastguard Worker return proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".img") 90*333d2b36SAndroid Build Coastguard Worker} 91*333d2b36SAndroid Build Coastguard Worker 92*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) GenerateAndroidBuildActions(ctx android.ModuleContext) { 93*333d2b36SAndroid Build Coastguard Worker builder := android.NewRuleBuilder(pctx, ctx) 94*333d2b36SAndroid Build Coastguard Worker 95*333d2b36SAndroid Build Coastguard Worker if a.properties.Src == nil { 96*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("src", "missing source file") 97*333d2b36SAndroid Build Coastguard Worker return 98*333d2b36SAndroid Build Coastguard Worker } 99*333d2b36SAndroid Build Coastguard Worker input := android.PathForModuleSrc(ctx, proptools.String(a.properties.Src)) 100*333d2b36SAndroid Build Coastguard Worker output := android.PathForModuleOut(ctx, a.installFileName()) 101*333d2b36SAndroid Build Coastguard Worker builder.Command().Text("cp").Input(input).Output(output) 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Worker cmd := builder.Command().BuiltTool("avbtool").Text("add_hash_footer") 104*333d2b36SAndroid Build Coastguard Worker 105*333d2b36SAndroid Build Coastguard Worker partition_name := proptools.StringDefault(a.properties.Partition_name, a.BaseModuleName()) 106*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--partition_name ", partition_name) 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker if a.properties.Partition_size == nil { 109*333d2b36SAndroid Build Coastguard Worker cmd.Flag("--dynamic_partition_size") 110*333d2b36SAndroid Build Coastguard Worker } else { 111*333d2b36SAndroid Build Coastguard Worker partition_size := proptools.Int(a.properties.Partition_size) 112*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--partition_size ", strconv.Itoa(partition_size)) 113*333d2b36SAndroid Build Coastguard Worker } 114*333d2b36SAndroid Build Coastguard Worker 115*333d2b36SAndroid Build Coastguard Worker key := android.PathForModuleSrc(ctx, proptools.String(a.properties.Private_key)) 116*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--key ", key) 117*333d2b36SAndroid Build Coastguard Worker 118*333d2b36SAndroid Build Coastguard Worker algorithm := proptools.StringDefault(a.properties.Algorithm, "SHA256_RSA4096") 119*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--algorithm ", algorithm) 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Worker if a.properties.Salt == nil { 122*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("salt", "missing salt value") 123*333d2b36SAndroid Build Coastguard Worker return 124*333d2b36SAndroid Build Coastguard Worker } 125*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--salt ", proptools.String(a.properties.Salt)) 126*333d2b36SAndroid Build Coastguard Worker 127*333d2b36SAndroid Build Coastguard Worker imagePaths := android.PathsForModuleSrc(ctx, a.properties.Include_descriptors_from_images) 128*333d2b36SAndroid Build Coastguard Worker for _, imagePath := range imagePaths { 129*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("--include_descriptors_from_image ", imagePath) 130*333d2b36SAndroid Build Coastguard Worker } 131*333d2b36SAndroid Build Coastguard Worker 132*333d2b36SAndroid Build Coastguard Worker for _, prop := range a.properties.Props { 133*333d2b36SAndroid Build Coastguard Worker addAvbProp(ctx, cmd, prop) 134*333d2b36SAndroid Build Coastguard Worker } 135*333d2b36SAndroid Build Coastguard Worker 136*333d2b36SAndroid Build Coastguard Worker if a.properties.Rollback_index != nil { 137*333d2b36SAndroid Build Coastguard Worker rollbackIndex := proptools.Int(a.properties.Rollback_index) 138*333d2b36SAndroid Build Coastguard Worker if rollbackIndex < 0 { 139*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") 140*333d2b36SAndroid Build Coastguard Worker } 141*333d2b36SAndroid Build Coastguard Worker cmd.Flag(fmt.Sprintf(" --rollback_index %d", rollbackIndex)) 142*333d2b36SAndroid Build Coastguard Worker } 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithOutput("--image ", output) 145*333d2b36SAndroid Build Coastguard Worker 146*333d2b36SAndroid Build Coastguard Worker builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName())) 147*333d2b36SAndroid Build Coastguard Worker 148*333d2b36SAndroid Build Coastguard Worker a.installDir = android.PathForModuleInstall(ctx, "etc") 149*333d2b36SAndroid Build Coastguard Worker ctx.InstallFile(a.installDir, a.installFileName(), output) 150*333d2b36SAndroid Build Coastguard Worker a.output = output 151*333d2b36SAndroid Build Coastguard Worker} 152*333d2b36SAndroid Build Coastguard Worker 153*333d2b36SAndroid Build Coastguard Workerfunc addAvbProp(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, prop avbProp) { 154*333d2b36SAndroid Build Coastguard Worker name := proptools.String(prop.Name) 155*333d2b36SAndroid Build Coastguard Worker value := proptools.String(prop.Value) 156*333d2b36SAndroid Build Coastguard Worker file := proptools.String(prop.File) 157*333d2b36SAndroid Build Coastguard Worker if name == "" { 158*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("name", "can't be empty") 159*333d2b36SAndroid Build Coastguard Worker return 160*333d2b36SAndroid Build Coastguard Worker } 161*333d2b36SAndroid Build Coastguard Worker if value == "" && file == "" { 162*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("value", "either value or file should be set") 163*333d2b36SAndroid Build Coastguard Worker return 164*333d2b36SAndroid Build Coastguard Worker } 165*333d2b36SAndroid Build Coastguard Worker if value != "" && file != "" { 166*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("value", "value and file can't be set at the same time") 167*333d2b36SAndroid Build Coastguard Worker return 168*333d2b36SAndroid Build Coastguard Worker } 169*333d2b36SAndroid Build Coastguard Worker 170*333d2b36SAndroid Build Coastguard Worker if value != "" { 171*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--prop ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, value))) 172*333d2b36SAndroid Build Coastguard Worker } else { 173*333d2b36SAndroid Build Coastguard Worker p := android.PathForModuleSrc(ctx, file) 174*333d2b36SAndroid Build Coastguard Worker cmd.Implicit(p) 175*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithArg("--prop_from_file ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, cmd.PathForInput(p)))) 176*333d2b36SAndroid Build Coastguard Worker } 177*333d2b36SAndroid Build Coastguard Worker} 178*333d2b36SAndroid Build Coastguard Worker 179*333d2b36SAndroid Build Coastguard Workervar _ android.AndroidMkEntriesProvider = (*avbAddHashFooter)(nil) 180*333d2b36SAndroid Build Coastguard Worker 181*333d2b36SAndroid Build Coastguard Worker// Implements android.AndroidMkEntriesProvider 182*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) AndroidMkEntries() []android.AndroidMkEntries { 183*333d2b36SAndroid Build Coastguard Worker return []android.AndroidMkEntries{android.AndroidMkEntries{ 184*333d2b36SAndroid Build Coastguard Worker Class: "ETC", 185*333d2b36SAndroid Build Coastguard Worker OutputFile: android.OptionalPathForPath(a.output), 186*333d2b36SAndroid Build Coastguard Worker ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 187*333d2b36SAndroid Build Coastguard Worker func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 188*333d2b36SAndroid Build Coastguard Worker entries.SetString("LOCAL_MODULE_PATH", a.installDir.String()) 189*333d2b36SAndroid Build Coastguard Worker entries.SetString("LOCAL_INSTALLED_MODULE_STEM", a.installFileName()) 190*333d2b36SAndroid Build Coastguard Worker }, 191*333d2b36SAndroid Build Coastguard Worker }, 192*333d2b36SAndroid Build Coastguard Worker }} 193*333d2b36SAndroid Build Coastguard Worker} 194*333d2b36SAndroid Build Coastguard Worker 195*333d2b36SAndroid Build Coastguard Workervar _ Filesystem = (*avbAddHashFooter)(nil) 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) OutputPath() android.Path { 198*333d2b36SAndroid Build Coastguard Worker return a.output 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) SignedOutputPath() android.Path { 202*333d2b36SAndroid Build Coastguard Worker return a.OutputPath() // always signed 203*333d2b36SAndroid Build Coastguard Worker} 204*333d2b36SAndroid Build Coastguard Worker 205*333d2b36SAndroid Build Coastguard Worker// TODO(b/185115783): remove when not needed as input to a prebuilt_etc rule 206*333d2b36SAndroid Build Coastguard Workervar _ android.SourceFileProducer = (*avbAddHashFooter)(nil) 207*333d2b36SAndroid Build Coastguard Worker 208*333d2b36SAndroid Build Coastguard Worker// Implements android.SourceFileProducer 209*333d2b36SAndroid Build Coastguard Workerfunc (a *avbAddHashFooter) Srcs() android.Paths { 210*333d2b36SAndroid Build Coastguard Worker return append(android.Paths{}, a.output) 211*333d2b36SAndroid Build Coastguard Worker} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Workertype avbAddHashFooterDefaults struct { 214*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 215*333d2b36SAndroid Build Coastguard Worker android.DefaultsModuleBase 216*333d2b36SAndroid Build Coastguard Worker} 217*333d2b36SAndroid Build Coastguard Worker 218*333d2b36SAndroid Build Coastguard Worker// avb_add_hash_footer_defaults provides a set of properties that can be inherited by other 219*333d2b36SAndroid Build Coastguard Worker// avb_add_hash_footer modules. A module can use the properties from an avb_add_hash_footer_defaults 220*333d2b36SAndroid Build Coastguard Worker// using `defaults: ["<:default_module_name>"]`. Properties of both modules are erged (when 221*333d2b36SAndroid Build Coastguard Worker// possible) by prepending the default module's values to the depending module's values. 222*333d2b36SAndroid Build Coastguard Workerfunc avbAddHashFooterDefaultsFactory() android.Module { 223*333d2b36SAndroid Build Coastguard Worker module := &avbAddHashFooterDefaults{} 224*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&avbAddHashFooterProperties{}) 225*333d2b36SAndroid Build Coastguard Worker android.InitDefaultsModule(module) 226*333d2b36SAndroid Build Coastguard Worker return module 227*333d2b36SAndroid Build Coastguard Worker} 228