Build vbmeta partitions with soong
AVB is Android Verified Boot:
https://source.android.com/docs/security/features/verifiedboot
It works by signing all the partitions, but then also including an extra
metadata paritition called vbmeta that depends on all the other
signed partitions. This creates a requirement that you update all those
partitions and the vbmeta partition together, so in order to relax that
requirement products can set up "chained" vbmeta partitions, where a
chained partition like vbmeta_system might contain the avb metadata for
just a few products. In cuttlefish vbmeta_system contains metadata about
product, system, and system_ext. Using chained partitions, that group of
partitions can be updated independently from the other signed
partitions.
This is a resubmission with changes starting from line 134 of
vbmeta_partitions.go to add default values for the key and algorithm,
and allow unset rollback indexes.
Bug: 377563298
Test: m nothing (the diff test currently fails, but this is a start)
Change-Id: I431df464b3841bd75d119233e64b207bb27b81a4
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index fe590a9..e677c95 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -44,6 +44,9 @@
type filesystemCreatorProps struct {
Generated_partition_types []string `blueprint:"mutated"`
Unsupported_partition_types []string `blueprint:"mutated"`
+
+ Vbmeta_module_names []string `blueprint:"mutated"`
+ Vbmeta_partition_names []string `blueprint:"mutated"`
}
type filesystemCreator struct {
@@ -67,16 +70,24 @@
}
func (f *filesystemCreator) createInternalModules(ctx android.LoadHookContext) {
- soongGeneratedPartitions := &ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions
- for _, partitionType := range *soongGeneratedPartitions {
+ soongGeneratedPartitions := generatedPartitions(ctx)
+ finalSoongGeneratedPartitions := make([]string, 0, len(soongGeneratedPartitions))
+ for _, partitionType := range soongGeneratedPartitions {
if f.createPartition(ctx, partitionType) {
f.properties.Generated_partition_types = append(f.properties.Generated_partition_types, partitionType)
+ finalSoongGeneratedPartitions = append(finalSoongGeneratedPartitions, partitionType)
} else {
f.properties.Unsupported_partition_types = append(f.properties.Unsupported_partition_types, partitionType)
- _, *soongGeneratedPartitions = android.RemoveFromList(partitionType, *soongGeneratedPartitions)
}
}
- f.createDeviceModule(ctx)
+
+ for _, x := range createVbmetaPartitions(ctx, finalSoongGeneratedPartitions) {
+ f.properties.Vbmeta_module_names = append(f.properties.Vbmeta_module_names, x.moduleName)
+ f.properties.Vbmeta_partition_names = append(f.properties.Vbmeta_partition_names, x.partitionName)
+ }
+
+ ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).soongGeneratedPartitions = finalSoongGeneratedPartitions
+ f.createDeviceModule(ctx, finalSoongGeneratedPartitions, f.properties.Vbmeta_module_names)
}
func generatedModuleName(cfg android.Config, suffix string) string {
@@ -91,7 +102,11 @@
return generatedModuleName(cfg, fmt.Sprintf("%s_image", partitionType))
}
-func (f *filesystemCreator) createDeviceModule(ctx android.LoadHookContext) {
+func (f *filesystemCreator) createDeviceModule(
+ ctx android.LoadHookContext,
+ generatedPartitionTypes []string,
+ vbmetaPartitions []string,
+) {
baseProps := &struct {
Name *string
}{
@@ -100,21 +115,22 @@
// Currently, only the system and system_ext partition module is created.
partitionProps := &filesystem.PartitionNameProperties{}
- if android.InList("system", f.properties.Generated_partition_types) {
+ if android.InList("system", generatedPartitionTypes) {
partitionProps.System_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system"))
}
- if android.InList("system_ext", f.properties.Generated_partition_types) {
+ if android.InList("system_ext", generatedPartitionTypes) {
partitionProps.System_ext_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "system_ext"))
}
- if android.InList("vendor", f.properties.Generated_partition_types) {
+ if android.InList("vendor", generatedPartitionTypes) {
partitionProps.Vendor_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor"))
}
- if android.InList("product", f.properties.Generated_partition_types) {
+ if android.InList("product", generatedPartitionTypes) {
partitionProps.Product_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "product"))
}
- if android.InList("odm", f.properties.Generated_partition_types) {
+ if android.InList("odm", generatedPartitionTypes) {
partitionProps.Odm_partition_name = proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "odm"))
}
+ partitionProps.Vbmeta_partitions = vbmetaPartitions
ctx.CreateModule(filesystem.AndroidDeviceFactory, baseProps, partitionProps)
}
@@ -344,12 +360,15 @@
type filesystemBaseProperty struct {
Name *string
Compile_multilib *string
+ Visibility []string
}
func generateBaseProps(namePtr *string) *filesystemBaseProperty {
return &filesystemBaseProperty{
Name: namePtr,
Compile_multilib: proptools.StringPtr("both"),
+ // The vbmeta modules are currently in the root directory and depend on the partitions
+ Visibility: []string{"//.", "//build/soong:__subpackages__"},
}
}
@@ -445,16 +464,42 @@
return file
}
+func createVbmetaDiff(ctx android.ModuleContext, vbmetaModuleName string, vbmetaPartitionName string) android.Path {
+ vbmetaModule := ctx.GetDirectDepWithTag(vbmetaModuleName, generatedVbmetaPartitionDepTag)
+ outputFilesProvider, ok := android.OtherModuleProvider(ctx, vbmetaModule, android.OutputFilesProvider)
+ if !ok {
+ ctx.ModuleErrorf("Expected module %s to provide OutputFiles", vbmetaModule)
+ }
+ if len(outputFilesProvider.DefaultOutputFiles) != 1 {
+ ctx.ModuleErrorf("Expected 1 output file from module %s", vbmetaModule)
+ }
+ soongVbMetaFile := outputFilesProvider.DefaultOutputFiles[0]
+ makeVbmetaFile := android.PathForArbitraryOutput(ctx, fmt.Sprintf("target/product/%s/%s.img", ctx.Config().DeviceName(), vbmetaPartitionName))
+
+ diffTestResultFile := android.PathForModuleOut(ctx, fmt.Sprintf("diff_test_%s.txt", vbmetaModuleName))
+ builder := android.NewRuleBuilder(pctx, ctx)
+ builder.Command().Text("diff").
+ Input(soongVbMetaFile).
+ Input(makeVbmetaFile)
+ builder.Command().Text("touch").Output(diffTestResultFile)
+ builder.Build(vbmetaModuleName+" diff test", vbmetaModuleName+" diff test")
+ return diffTestResultFile
+}
+
type systemImageDepTagType struct {
blueprint.BaseDependencyTag
}
var generatedFilesystemDepTag systemImageDepTagType
+var generatedVbmetaPartitionDepTag systemImageDepTagType
func (f *filesystemCreator) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, partitionType := range f.properties.Generated_partition_types {
ctx.AddDependency(ctx.Module(), generatedFilesystemDepTag, generatedModuleNameForPartition(ctx.Config(), partitionType))
}
+ for _, vbmetaModule := range f.properties.Vbmeta_module_names {
+ ctx.AddDependency(ctx.Module(), generatedVbmetaPartitionDepTag, vbmetaModule)
+ }
}
func (f *filesystemCreator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -484,6 +529,11 @@
diffTestFiles = append(diffTestFiles, diffTestFile)
ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", partitionType), diffTestFile)
}
+ for i, vbmetaModule := range f.properties.Vbmeta_module_names {
+ diffTestFile := createVbmetaDiff(ctx, vbmetaModule, f.properties.Vbmeta_partition_names[i])
+ diffTestFiles = append(diffTestFiles, diffTestFile)
+ ctx.Phony(fmt.Sprintf("soong_generated_%s_filesystem_test", f.properties.Vbmeta_partition_names[i]), diffTestFile)
+ }
ctx.Phony("soong_generated_filesystem_tests", diffTestFiles...)
}