diff options
Diffstat (limited to 'filesystem/filesystem.go')
| -rw-r--r-- | filesystem/filesystem.go | 216 |
1 files changed, 162 insertions, 54 deletions
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index b5f7e486d..6dfbfd1be 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -53,6 +53,12 @@ func registerMutators(ctx android.RegistrationContext) { }) } +// Remember to add referenced files to implicits! +var textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{ + Command: "build/soong/scripts/text_file_processor.py $in $out", + CommandDeps: []string{"build/soong/scripts/text_file_processor.py"}, +}) + type filesystem struct { android.ModuleBase android.PackagingBase @@ -92,6 +98,14 @@ type SymlinkDefinition struct { Name *string } +// CopyWithNamePrefix returns a new [SymlinkDefinition] with prefix added to Name. +func (s *SymlinkDefinition) CopyWithNamePrefix(prefix string) SymlinkDefinition { + return SymlinkDefinition{ + Target: s.Target, + Name: proptools.StringPtr(filepath.Join(prefix, proptools.String(s.Name))), + } +} + type FilesystemProperties struct { // When set to true, sign the image with avbtool. Default is false. Use_avb *bool @@ -107,6 +121,12 @@ type FilesystemProperties struct { // avbtool. Default used by avbtool is sha1. Avb_hash_algorithm *string + // The security patch passed to as the com.android.build.<type>.security_patch avb property. + Security_patch *string + + // Whether or not to use forward-error-correction codes when signing with AVB. Defaults to true. + Use_fec *bool + // The index used to prevent rollback of the image. Only used if use_avb is true. Rollback_index *int64 @@ -121,9 +141,13 @@ type FilesystemProperties struct { // checks, and will be used in the future for API surface checks. Partition_type *string - // file_contexts file to make image. Currently, only ext4 is supported. + // file_contexts file to make image. Currently, only ext4 is supported. These file contexts + // will be compiled with sefcontext_compile File_contexts *string `android:"path"` + // The selinux file contexts, after having already run them through sefcontext_compile + Precompiled_file_contexts *string `android:"path"` + // Base directory relative to root, to which deps are installed, e.g. "system". Default is "." // (root). Base_dir *string @@ -131,6 +155,11 @@ type FilesystemProperties struct { // Directories to be created under root. e.g. /dev, /proc, etc. Dirs proptools.Configurable[[]string] + // List of filesystem modules to include in creating the partition. The root directory of + // the provided filesystem modules are included in creating the partition. + // This is only supported for cpio and compressed cpio filesystem types. + Include_files_of []string + // Symbolic links to be created under root with "ln -sf <target> <name>". Symlinks []SymlinkDefinition @@ -157,6 +186,11 @@ type FilesystemProperties struct { // Install aconfig_flags.pb file for the modules installed in this partition. Gen_aconfig_flags_pb *bool + // List of names of other filesystem partitions to import their aconfig flags from. + // This is used for the system partition to import system_ext's aconfig flags, as currently + // those are considered one "container": aosp/3261300 + Import_aconfig_flags_from []string + Fsverity fsverityProperties // If this property is set to true, the filesystem will call ctx.UncheckedModule(), causing @@ -257,6 +291,8 @@ type interPartitionDepTag struct { var interPartitionDependencyTag = interPartitionDepTag{} +var interPartitionInstallDependencyTag = interPartitionDepTag{} + var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil) func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {} @@ -285,6 +321,12 @@ func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) { if f.properties.Android_filesystem_deps.System_ext != nil { ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext)) } + for _, partition := range f.properties.Import_aconfig_flags_from { + ctx.AddDependency(ctx.Module(), importAconfigDependencyTag, partition) + } + for _, partition := range f.properties.Include_files_of { + ctx.AddDependency(ctx.Module(), interPartitionInstallDependencyTag, partition) + } } type fsType int @@ -303,8 +345,14 @@ func (fs fsType) IsUnknown() bool { } type FilesystemInfo struct { + // The built filesystem image + Output android.Path // A text file containing the list of paths installed on the partition. FileListFile android.Path + // The root staging directory used to build the output filesystem. If consuming this, make sure + // to add a dependency on the Output file, as you cannot add dependencies on directories + // in ninja. + RootDir android.Path } var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]() @@ -378,13 +426,19 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { if f.filesystemBuilder.ShouldUseVintfFragmentModuleOnly() { f.validateVintfFragments(ctx) } + + if len(f.properties.Include_files_of) > 0 && !android.InList(f.fsType(ctx), []fsType{compressedCpioType, cpioType}) { + ctx.PropertyErrorf("include_files_of", "include_files_of is only supported for cpio and compressed cpio filesystem types.") + } + + var rootDir android.OutputPath switch f.fsType(ctx) { case ext4Type, erofsType, f2fsType: - f.output = f.buildImageUsingBuildImage(ctx) + f.output, rootDir = f.buildImageUsingBuildImage(ctx) case compressedCpioType: - f.output = f.buildCpioImage(ctx, true) + f.output, rootDir = f.buildCpioImage(ctx, true) case cpioType: - f.output = f.buildCpioImage(ctx, false) + f.output, rootDir = f.buildCpioImage(ctx, false) default: return } @@ -393,11 +447,17 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.InstallFile(f.installDir, f.installFileName(), f.output) ctx.SetOutputFiles([]android.Path{f.output}, "") + if f.partitionName() == "recovery" { + rootDir = rootDir.Join(ctx, "root") + } + fileListFile := android.PathForModuleOut(ctx, "fileList") android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{ + Output: f.output, FileListFile: fileListFile, + RootDir: rootDir, }) f.fileListFile = fileListFile @@ -444,7 +504,7 @@ func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) { } func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.Path) { - partitionBaseDir := android.PathForModuleOut(ctx, "root", f.partitionName()).String() + "/" + partitionBaseDir := android.PathForModuleOut(ctx, f.rootDirString(), proptools.String(f.properties.Base_dir)).String() + "/" relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir) if inTargetPartition { @@ -505,6 +565,12 @@ func (f *filesystem) buildNonDepsFiles(ctx android.ModuleContext, builder *andro builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String()) f.appendToEntry(ctx, dst) } + + // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2835;drc=b186569ef00ff2f2a1fab28aedc75ebc32bcd67b + if f.partitionName() == "recovery" { + builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, "root/linkerconfig").String()) + builder.Command().Text("touch").Text(rootDir.Join(ctx, "root/linkerconfig/ld.config.txt").String()) + } } func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir, rebasedDir android.WritablePath) []string { @@ -534,8 +600,12 @@ func (f *filesystem) copyFilesToProductOut(ctx android.ModuleContext, builder *a builder.Command().Textf("cp -prf %s/* %s", rebasedDir, installPath) } -func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.Path { - rootDir := android.PathForModuleOut(ctx, "root").OutputPath +func (f *filesystem) rootDirString() string { + return f.partitionName() +} + +func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) (android.Path, android.OutputPath) { + rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath rebasedDir := rootDir if f.properties.Base_dir != nil { rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir) @@ -563,18 +633,28 @@ func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) androi FlagWithArg("--out_system=", rootDir.String()+"/system") propFile, toolDeps := f.buildPropFile(ctx) + + // Most of the time, if build_image were to call a host tool, it accepts the path to the + // host tool in a field in the prop file. However, it doesn't have that option for fec, which + // it expects to just be on the PATH. Add fec to the PATH. + fec := ctx.Config().HostToolPath(ctx, "fec") + pathToolDirs := []string{filepath.Dir(fec.String())} + output := android.PathForModuleOut(ctx, f.installFileName()) - builder.Command().BuiltTool("build_image"). + builder.Command(). + Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")). + BuiltTool("build_image"). Text(rootDir.String()). // input directory Input(propFile). Implicits(toolDeps). + Implicit(fec). Output(output). Text(rootDir.String()) // directory where to find fs_config_files|dirs // rootDir is not deleted. Might be useful for quick inspection. builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) - return output + return output, rootDir } func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path { @@ -587,11 +667,6 @@ func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path { return fcBin } -// Calculates avb_salt from entry list (sorted) for deterministic output. -func (f *filesystem) salt() string { - return sha1sum(f.entries) -} - func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, android.Paths) { var deps android.Paths var propFileString strings.Builder @@ -634,10 +709,15 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool")) algorithm := proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096") addStr("avb_algorithm", algorithm) - key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key)) - addPath("avb_key_path", key) + if f.properties.Avb_private_key != nil { + key := android.PathForModuleSrc(ctx, *f.properties.Avb_private_key) + addPath("avb_key_path", key) + } addStr("partition_name", f.partitionName()) - avb_add_hashtree_footer_args := "--do_not_generate_fec" + avb_add_hashtree_footer_args := "" + if !proptools.BoolDefault(f.properties.Use_fec, true) { + avb_add_hashtree_footer_args += " --do_not_generate_fec" + } if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" { avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm } @@ -648,19 +728,33 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and } avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) } - securityPatchKey := "com.android.build." + f.partitionName() + ".security_patch" - securityPatchValue := ctx.Config().PlatformSecurityPatch() - avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) + // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because + // the build number changed, and we don't want to trigger rebuilds solely based on the build + // number. + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) + if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { + avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) + } addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args) - addStr("avb_salt", f.salt()) } - if proptools.String(f.properties.File_contexts) != "" { + if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil { + ctx.ModuleErrorf("file_contexts and precompiled_file_contexts cannot both be set") + } else if f.properties.File_contexts != nil { addPath("selinux_fc", f.buildFileContexts(ctx)) + } else if f.properties.Precompiled_file_contexts != nil { + src := android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts) + if src != nil { + addPath("selinux_fc", src) + } } if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" { addStr("timestamp", timestamp) + } else if ctx.Config().Getenv("USE_FIXED_TIMESTAMP_IMG_FILES") == "true" { + addStr("use_fixed_timestamp", "true") } + if uuid := proptools.String(f.properties.Uuid); uuid != "" { addStr("uuid", uuid) addStr("hash_seed", uuid) @@ -677,11 +771,10 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and switch fst { case erofsType: // Add erofs properties - if compressor := f.properties.Erofs.Compressor; compressor != nil { - addStr("erofs_default_compressor", proptools.String(compressor)) - } - if compressHints := f.properties.Erofs.Compress_hints; compressHints != nil { - addPath("erofs_default_compress_hints", android.PathForModuleSrc(ctx, *compressHints)) + addStr("erofs_default_compressor", proptools.StringDefault(f.properties.Erofs.Compressor, "lz4hc,9")) + if f.properties.Erofs.Compress_hints != nil { + src := android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints) + addPath("erofs_default_compress_hints", src) } if proptools.BoolDefault(f.properties.Erofs.Sparse, true) { // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b @@ -695,8 +788,14 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, and } f.checkFsTypePropertyError(ctx, fst, fsTypeStr(fst)) + propFilePreProcessing := android.PathForModuleOut(ctx, "prop_pre_processing") + android.WriteFileRuleVerbatim(ctx, propFilePreProcessing, propFileString.String()) propFile := android.PathForModuleOut(ctx, "prop") - android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String()) + ctx.Build(pctx, android.BuildParams{ + Rule: textFileProcessorRule, + Input: propFilePreProcessing, + Output: propFile, + }) return propFile, deps } @@ -720,7 +819,20 @@ func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsTyp } } -func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.Path { +func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, partitions android.Paths) { + ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { + if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok { + rootDirs = append(rootDirs, fsProvider.RootDir) + partitions = append(partitions, fsProvider.Output) + } else { + ctx.PropertyErrorf("include_files_of", "only filesystem modules can be listed in "+ + "include_files_of but %s is not a filesystem module", m.Name()) + } + }) + return rootDirs, partitions +} + +func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) (android.Path, android.OutputPath) { if proptools.Bool(f.properties.Use_avb) { ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+ "Consider adding this to bootimg module and signing the entire boot image.") @@ -734,7 +846,7 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) ctx.PropertyErrorf("include_make_built_files", "include_make_built_files is not supported for compressed cpio image.") } - rootDir := android.PathForModuleOut(ctx, "root").OutputPath + rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath rebasedDir := rootDir if f.properties.Base_dir != nil { rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir) @@ -752,10 +864,18 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir) f.copyFilesToProductOut(ctx, builder, rebasedDir) + rootDirs, partitions := includeFilesRootDir(ctx) + output := android.PathForModuleOut(ctx, f.installFileName()) cmd := builder.Command(). BuiltTool("mkbootfs"). Text(rootDir.String()) // input directory + + for i := range len(rootDirs) { + cmd.Text(rootDirs[i].String()) + } + cmd.Implicits(partitions) + if nodeList := f.properties.Dev_nodes_description_file; nodeList != nil { cmd.FlagWithInput("-n ", android.PathForModuleSrc(ctx, proptools.String(nodeList))) } @@ -773,7 +893,7 @@ func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) // rootDir is not deleted. Might be useful for quick inspection. builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) - return output + return output, rootDir } var validPartitions = []string{ @@ -819,30 +939,10 @@ func (f *filesystem) buildEventLogtagsFile(ctx android.ModuleContext, builder *a return } - logtagsFilePaths := make(map[string]bool) - ctx.WalkDeps(func(child, parent android.Module) bool { - if logtagsInfo, ok := android.OtherModuleProvider(ctx, child, android.LogtagsProviderKey); ok { - for _, path := range logtagsInfo.Logtags { - logtagsFilePaths[path.String()] = true - } - } - return true - }) - - if len(logtagsFilePaths) == 0 { - return - } - etcPath := rebasedDir.Join(ctx, "etc") eventLogtagsPath := etcPath.Join(ctx, "event-log-tags") builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String()) - cmd := builder.Command().BuiltTool("merge-event-log-tags"). - FlagWithArg("-o ", eventLogtagsPath.String()). - FlagWithInput("-m ", android.MergedLogtagsPath(ctx)) - - for _, path := range android.SortedKeys(logtagsFilePaths) { - cmd.Text(path) - } + builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String()) f.appendToEntry(ctx, eventLogtagsPath) } @@ -853,8 +953,10 @@ func (f *filesystem) BuildLinkerConfigFile(ctx android.ModuleContext, builder *a } provideModules, _ := f.getLibsForLinkerConfig(ctx) + intermediateOutput := android.PathForModuleOut(ctx, "linker.config.pb") + linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, intermediateOutput) output := rebasedDir.Join(ctx, "etc", "linker.config.pb") - linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, output) + builder.Command().Text("cp").Input(intermediateOutput).Output(output) f.appendToEntry(ctx, output) } @@ -982,7 +1084,7 @@ func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]androi ctx.WalkDeps(func(child, parent android.Module) bool { for _, ps := range android.OtherModuleProviderOrDefault( ctx, child, android.InstallFilesProvider).PackagingSpecs { - if _, ok := deps[ps.RelPathInPackage()]; ok { + if _, ok := deps[ps.RelPathInPackage()]; ok && ps.Partition() == f.PartitionType() { modulesInPackageByModule[child] = true modulesInPackageByName[child.Name()] = true return true @@ -1044,6 +1146,12 @@ func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) { } thisPartition := f.PartitionType() if thisPartition != "vendor" && thisPartition != "product" { + if f.properties.Android_filesystem_deps.System != nil { + ctx.PropertyErrorf("android_filesystem_deps.system", "only vendor or product partitions can use android_filesystem_deps") + } + if f.properties.Android_filesystem_deps.System_ext != nil { + ctx.PropertyErrorf("android_filesystem_deps.system_ext", "only vendor or product partitions can use android_filesystem_deps") + } return } ctx.WalkDeps(func(child, parent android.Module) bool { |