avb_add_hash_footer.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // Copyright (C) 2022 The Android Open Source Project
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package filesystem
  15. import (
  16. "fmt"
  17. "strconv"
  18. "github.com/google/blueprint/proptools"
  19. "android/soong/android"
  20. )
  21. type avbAddHashFooter struct {
  22. android.ModuleBase
  23. properties avbAddHashFooterProperties
  24. output android.OutputPath
  25. installDir android.InstallPath
  26. }
  27. type avbProp struct {
  28. // Name of a property
  29. Name *string
  30. // Value of a property. Can't be used together with `file`.
  31. Value *string
  32. // File from which the value of the prop is read from. Can't be used together with `value`.
  33. File *string `android:"path,arch_variant"`
  34. }
  35. type avbAddHashFooterProperties struct {
  36. // Source file of this image. Can reference a genrule type module with the ":module" syntax.
  37. Src *string `android:"path,arch_variant"`
  38. // Set the name of the output. Defaults to <module_name>.img.
  39. Filename *string
  40. // Name of the image partition. Defaults to the name of this module.
  41. Partition_name *string
  42. // Size of the partition. Defaults to dynamically calculating the size.
  43. Partition_size *int64
  44. // Path to the private key that avbtool will use to sign this image.
  45. Private_key *string `android:"path"`
  46. // Algorithm that avbtool will use to sign this image. Default is SHA256_RSA4096.
  47. Algorithm *string
  48. // The salt in hex. Required for reproducible builds.
  49. Salt *string
  50. // List of properties to add to the footer
  51. Props []avbProp
  52. // Include descriptors from images
  53. Include_descriptors_from_images []string `android:"path,arch_variant"`
  54. }
  55. // The AVB footer adds verification information to the image.
  56. func avbAddHashFooterFactory() android.Module {
  57. module := &avbAddHashFooter{}
  58. module.AddProperties(&module.properties)
  59. android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
  60. return module
  61. }
  62. func (a *avbAddHashFooter) installFileName() string {
  63. return proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".img")
  64. }
  65. func (a *avbAddHashFooter) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  66. builder := android.NewRuleBuilder(pctx, ctx)
  67. if a.properties.Src == nil {
  68. ctx.PropertyErrorf("src", "missing source file")
  69. return
  70. }
  71. input := android.PathForModuleSrc(ctx, proptools.String(a.properties.Src))
  72. a.output = android.PathForModuleOut(ctx, a.installFileName()).OutputPath
  73. builder.Command().Text("cp").Input(input).Output(a.output)
  74. cmd := builder.Command().BuiltTool("avbtool").Text("add_hash_footer")
  75. partition_name := proptools.StringDefault(a.properties.Partition_name, a.BaseModuleName())
  76. cmd.FlagWithArg("--partition_name ", partition_name)
  77. if a.properties.Partition_size == nil {
  78. cmd.Flag("--dynamic_partition_size")
  79. } else {
  80. partition_size := proptools.Int(a.properties.Partition_size)
  81. cmd.FlagWithArg("--partition_size ", strconv.Itoa(partition_size))
  82. }
  83. key := android.PathForModuleSrc(ctx, proptools.String(a.properties.Private_key))
  84. cmd.FlagWithInput("--key ", key)
  85. algorithm := proptools.StringDefault(a.properties.Algorithm, "SHA256_RSA4096")
  86. cmd.FlagWithArg("--algorithm ", algorithm)
  87. if a.properties.Salt == nil {
  88. ctx.PropertyErrorf("salt", "missing salt value")
  89. return
  90. }
  91. cmd.FlagWithArg("--salt ", proptools.String(a.properties.Salt))
  92. imagePaths := android.PathsForModuleSrc(ctx, a.properties.Include_descriptors_from_images)
  93. for _, imagePath := range imagePaths {
  94. cmd.FlagWithInput("--include_descriptors_from_image ", imagePath)
  95. }
  96. for _, prop := range a.properties.Props {
  97. addAvbProp(ctx, cmd, prop)
  98. }
  99. cmd.FlagWithOutput("--image ", a.output)
  100. builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName()))
  101. a.installDir = android.PathForModuleInstall(ctx, "etc")
  102. ctx.InstallFile(a.installDir, a.installFileName(), a.output)
  103. }
  104. func addAvbProp(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, prop avbProp) {
  105. name := proptools.String(prop.Name)
  106. value := proptools.String(prop.Value)
  107. file := proptools.String(prop.File)
  108. if name == "" {
  109. ctx.PropertyErrorf("name", "can't be empty")
  110. return
  111. }
  112. if value == "" && file == "" {
  113. ctx.PropertyErrorf("value", "either value or file should be set")
  114. return
  115. }
  116. if value != "" && file != "" {
  117. ctx.PropertyErrorf("value", "value and file can't be set at the same time")
  118. return
  119. }
  120. if value != "" {
  121. cmd.FlagWithArg("--prop ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, value)))
  122. } else {
  123. p := android.PathForModuleSrc(ctx, file)
  124. cmd.Implicit(p)
  125. cmd.FlagWithArg("--prop_from_file ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, cmd.PathForInput(p))))
  126. }
  127. }
  128. var _ android.AndroidMkEntriesProvider = (*avbAddHashFooter)(nil)
  129. // Implements android.AndroidMkEntriesProvider
  130. func (a *avbAddHashFooter) AndroidMkEntries() []android.AndroidMkEntries {
  131. return []android.AndroidMkEntries{android.AndroidMkEntries{
  132. Class: "ETC",
  133. OutputFile: android.OptionalPathForPath(a.output),
  134. ExtraEntries: []android.AndroidMkExtraEntriesFunc{
  135. func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
  136. entries.SetString("LOCAL_MODULE_PATH", a.installDir.String())
  137. entries.SetString("LOCAL_INSTALLED_MODULE_STEM", a.installFileName())
  138. },
  139. },
  140. }}
  141. }
  142. var _ Filesystem = (*avbAddHashFooter)(nil)
  143. func (a *avbAddHashFooter) OutputPath() android.Path {
  144. return a.output
  145. }
  146. func (a *avbAddHashFooter) SignedOutputPath() android.Path {
  147. return a.OutputPath() // always signed
  148. }
  149. // TODO(b/185115783): remove when not needed as input to a prebuilt_etc rule
  150. var _ android.SourceFileProducer = (*avbAddHashFooter)(nil)
  151. // Implements android.SourceFileProducer
  152. func (a *avbAddHashFooter) Srcs() android.Paths {
  153. return append(android.Paths{}, a.output)
  154. }