From 635e788274aa17beed18ed5174e709202260bd8a Mon Sep 17 00:00:00 2001 From: Justin Yun Date: Thu, 4 Jul 2024 14:50:57 +0900 Subject: [PATCH] Define otacerts_zip module in soong To move the otacerts module from make to soong, define a new module type otacerts_zip module. This module collects key files from PRODUCT_DEFAULT_DEV_CERTIFICATE and PRODUCT_EXTRA_OTA_KEYS (PRODUCT_EXTRA_RECOVERY_KEYS for recovery) to install the zipped file in etc. otacerts_zip module is available to recovery to install the otacerts.zip file in the recovery partition. Bug: 335364209 Test: Define "PRODUCT_DEFAULT_DEV_CERTIFICATE := \ build/make/target/product/security/testkey" and m aosp_cf_system_x86_64 Change-Id: Ib5b671e9caef0403c6d9d69bfab29be248d7086c --- android/config.go | 16 +++++ android/variable.go | 6 +- etc/Android.bp | 3 +- etc/otacerts_zip.go | 146 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 etc/otacerts_zip.go diff --git a/android/config.go b/android/config.go index cda01f090..d16377d7b 100644 --- a/android/config.go +++ b/android/config.go @@ -1055,6 +1055,22 @@ func (c *config) DefaultAppCertificate(ctx PathContext) (pem, key SourcePath) { return defaultDir.Join(ctx, "testkey.x509.pem"), defaultDir.Join(ctx, "testkey.pk8") } +func (c *config) ExtraOtaKeys(ctx PathContext, recovery bool) []SourcePath { + var otaKeys []string + if recovery { + otaKeys = c.productVariables.ExtraOtaRecoveryKeys + } else { + otaKeys = c.productVariables.ExtraOtaKeys + } + + otaPaths := make([]SourcePath, len(otaKeys)) + for i, key := range otaKeys { + otaPaths[i] = PathForSource(ctx, key+".x509.pem") + } + + return otaPaths +} + func (c *config) BuildKeys() string { defaultCert := String(c.productVariables.DefaultAppCertificate) if defaultCert == "" || defaultCert == filepath.Join(testKeyDir, "testkey") { diff --git a/android/variable.go b/android/variable.go index a331439f6..d144f7d43 100644 --- a/android/variable.go +++ b/android/variable.go @@ -274,8 +274,10 @@ type ProductVariables struct { AAPTPreferredConfig *string `json:",omitempty"` AAPTPrebuiltDPI []string `json:",omitempty"` - DefaultAppCertificate *string `json:",omitempty"` - MainlineSepolicyDevCertificates *string `json:",omitempty"` + DefaultAppCertificate *string `json:",omitempty"` + ExtraOtaKeys []string `json:",omitempty"` + ExtraOtaRecoveryKeys []string `json:",omitempty"` + MainlineSepolicyDevCertificates *string `json:",omitempty"` AppsDefaultVersionName *string `json:",omitempty"` diff --git a/etc/Android.bp b/etc/Android.bp index 97788e488..f02c12a2a 100644 --- a/etc/Android.bp +++ b/etc/Android.bp @@ -11,8 +11,9 @@ bootstrap_go_package { "soong-android", ], srcs: [ - "prebuilt_etc.go", "install_symlink.go", + "otacerts_zip.go", + "prebuilt_etc.go", ], testSrcs: [ "prebuilt_etc_test.go", diff --git a/etc/otacerts_zip.go b/etc/otacerts_zip.go new file mode 100644 index 000000000..b6f175a2d --- /dev/null +++ b/etc/otacerts_zip.go @@ -0,0 +1,146 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package etc + +import ( + "android/soong/android" + + "github.com/google/blueprint/proptools" +) + +func init() { + RegisterOtacertsZipBuildComponents(android.InitRegistrationContext) +} + +func RegisterOtacertsZipBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("otacerts_zip", otacertsZipFactory) +} + +type otacertsZipProperties struct { + // Make this module available when building for recovery. + // Only the recovery partition is available. + Recovery_available *bool + + // Optional subdirectory under which the zip file is installed into. + Relative_install_path *string + + // Optional name for the installed file. If unspecified, otacerts.zip is used. + Filename *string +} + +type otacertsZipModule struct { + android.ModuleBase + + properties otacertsZipProperties + outputPath android.OutputPath +} + +// otacerts_zip collects key files defined in PRODUCT_DEFAULT_DEV_CERTIFICATE +// and PRODUCT_EXTRA_OTA_KEYS for system or PRODUCT_EXTRA_RECOVERY_KEYS for +// recovery image. The output file (otacerts.zip by default) is installed into +// the relative_install_path directory under the etc directory of the target +// partition. +func otacertsZipFactory() android.Module { + module := &otacertsZipModule{} + module.AddProperties(&module.properties) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) + return module +} + +var _ android.ImageInterface = (*otacertsZipModule)(nil) + +func (m *otacertsZipModule) ImageMutatorBegin(ctx android.BaseModuleContext) {} + +func (m *otacertsZipModule) VendorVariantNeeded(ctx android.BaseModuleContext) bool { + return false +} + +func (m *otacertsZipModule) ProductVariantNeeded(ctx android.BaseModuleContext) bool { + return false +} + +func (m *otacertsZipModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool { + return !m.ModuleBase.InstallInRecovery() +} + +func (m *otacertsZipModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { + return false +} + +func (m *otacertsZipModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { + return false +} + +func (m *otacertsZipModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { + return false +} + +func (m *otacertsZipModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { + return proptools.Bool(m.properties.Recovery_available) || m.ModuleBase.InstallInRecovery() +} + +func (m *otacertsZipModule) ExtraImageVariations(ctx android.BaseModuleContext) []string { + return nil +} + +func (m *otacertsZipModule) SetImageVariation(ctx android.BaseModuleContext, variation string) { +} + +func (m *otacertsZipModule) InRecovery() bool { + return m.ModuleBase.InRecovery() || m.ModuleBase.InstallInRecovery() +} + +func (m *otacertsZipModule) InstallInRecovery() bool { + return m.InRecovery() +} + +func (m *otacertsZipModule) outputFileName() string { + // Use otacerts.zip if not specified. + return proptools.StringDefault(m.properties.Filename, "otacerts.zip") +} + +func (m *otacertsZipModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Read .x509.pem file defined in PRODUCT_DEFAULT_DEV_CERTIFICATE or the default test key. + pem, _ := ctx.Config().DefaultAppCertificate(ctx) + // Read .x509.pem files listed in PRODUCT_EXTRA_OTA_KEYS or PRODUCT_EXTRA_RECOVERY_KEYS. + extras := ctx.Config().ExtraOtaKeys(ctx, m.InRecovery()) + srcPaths := append([]android.SourcePath{pem}, extras...) + m.outputPath = android.PathForModuleOut(ctx, m.outputFileName()).OutputPath + + rule := android.NewRuleBuilder(pctx, ctx) + cmd := rule.Command().BuiltTool("soong_zip"). + FlagWithOutput("-o ", m.outputPath). + Flag("-j "). + Flag("-symlinks=false ") + for _, src := range srcPaths { + cmd.FlagWithInput("-f ", src) + } + rule.Build(ctx.ModuleName(), "Generating the otacerts zip file") + + installPath := android.PathForModuleInstall(ctx, "etc", proptools.String(m.properties.Relative_install_path)) + ctx.InstallFile(installPath, m.outputFileName(), m.outputPath) +} + +func (m *otacertsZipModule) AndroidMkEntries() []android.AndroidMkEntries { + nameSuffix := "" + if m.InRecovery() { + nameSuffix = ".recovery" + } + return []android.AndroidMkEntries{android.AndroidMkEntries{ + Class: "ETC", + SubName: nameSuffix, + OutputFile: android.OptionalPathForPath(m.outputPath), + }} +}