xref: /aosp_15_r20/build/soong/filesystem/bootimg.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2021 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	"strings"
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
23*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Workerfunc init() {
29*333d2b36SAndroid Build Coastguard Worker	android.RegisterModuleType("bootimg", BootimgFactory)
30*333d2b36SAndroid Build Coastguard Worker}
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Workertype bootimg struct {
33*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Worker	properties BootimgProperties
36*333d2b36SAndroid Build Coastguard Worker
37*333d2b36SAndroid Build Coastguard Worker	output     android.Path
38*333d2b36SAndroid Build Coastguard Worker	installDir android.InstallPath
39*333d2b36SAndroid Build Coastguard Worker
40*333d2b36SAndroid Build Coastguard Worker	bootImageType bootImageType
41*333d2b36SAndroid Build Coastguard Worker}
42*333d2b36SAndroid Build Coastguard Worker
43*333d2b36SAndroid Build Coastguard Workertype BootimgProperties struct {
44*333d2b36SAndroid Build Coastguard Worker	// Set the name of the output. Defaults to <module_name>.img.
45*333d2b36SAndroid Build Coastguard Worker	Stem *string
46*333d2b36SAndroid Build Coastguard Worker
47*333d2b36SAndroid Build Coastguard Worker	// Path to the linux kernel prebuilt file
48*333d2b36SAndroid Build Coastguard Worker	Kernel_prebuilt *string `android:"arch_variant,path"`
49*333d2b36SAndroid Build Coastguard Worker
50*333d2b36SAndroid Build Coastguard Worker	// Filesystem module that is used as ramdisk
51*333d2b36SAndroid Build Coastguard Worker	Ramdisk_module *string
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker	// Path to the device tree blob (DTB) prebuilt file to add to this boot image
54*333d2b36SAndroid Build Coastguard Worker	Dtb_prebuilt *string `android:"arch_variant,path"`
55*333d2b36SAndroid Build Coastguard Worker
56*333d2b36SAndroid Build Coastguard Worker	// Header version number. Must be set to one of the version numbers that are currently
57*333d2b36SAndroid Build Coastguard Worker	// supported. Refer to
58*333d2b36SAndroid Build Coastguard Worker	// https://source.android.com/devices/bootloader/boot-image-header
59*333d2b36SAndroid Build Coastguard Worker	Header_version *string
60*333d2b36SAndroid Build Coastguard Worker
61*333d2b36SAndroid Build Coastguard Worker	// Determines the specific type of boot image this module is building. Can be boot,
62*333d2b36SAndroid Build Coastguard Worker	// vendor_boot or init_boot. Defaults to boot.
63*333d2b36SAndroid Build Coastguard Worker	// Refer to https://source.android.com/devices/bootloader/partitions/vendor-boot-partitions
64*333d2b36SAndroid Build Coastguard Worker	// for vendor_boot.
65*333d2b36SAndroid Build Coastguard Worker	// Refer to https://source.android.com/docs/core/architecture/partitions/generic-boot for
66*333d2b36SAndroid Build Coastguard Worker	// init_boot.
67*333d2b36SAndroid Build Coastguard Worker	Boot_image_type *string
68*333d2b36SAndroid Build Coastguard Worker
69*333d2b36SAndroid Build Coastguard Worker	// Optional kernel commandline arguments
70*333d2b36SAndroid Build Coastguard Worker	Cmdline []string `android:"arch_variant"`
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker	// File that contains bootconfig parameters. This can be set only when `vendor_boot` is true
73*333d2b36SAndroid Build Coastguard Worker	// and `header_version` is greater than or equal to 4.
74*333d2b36SAndroid Build Coastguard Worker	Bootconfig *string `android:"arch_variant,path"`
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Worker	// The size of the partition on the device. It will be a build error if this built partition
77*333d2b36SAndroid Build Coastguard Worker	// image exceeds this size.
78*333d2b36SAndroid Build Coastguard Worker	Partition_size *int64
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker	// When set to true, sign the image with avbtool. Default is false.
81*333d2b36SAndroid Build Coastguard Worker	Use_avb *bool
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Worker	// This can either be "default", or "make_legacy". "make_legacy" will sign the boot image
84*333d2b36SAndroid Build Coastguard Worker	// like how build/make/core/Makefile does, to get bit-for-bit backwards compatibility. But
85*333d2b36SAndroid Build Coastguard Worker	// we may want to reconsider if it's necessary to have two modes in the future. The default
86*333d2b36SAndroid Build Coastguard Worker	// is "default"
87*333d2b36SAndroid Build Coastguard Worker	Avb_mode *string
88*333d2b36SAndroid Build Coastguard Worker
89*333d2b36SAndroid Build Coastguard Worker	// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
90*333d2b36SAndroid Build Coastguard Worker	Partition_name *string
91*333d2b36SAndroid Build Coastguard Worker
92*333d2b36SAndroid Build Coastguard Worker	// Path to the private key that avbtool will use to sign this filesystem image.
93*333d2b36SAndroid Build Coastguard Worker	// TODO(jiyong): allow apex_key to be specified here
94*333d2b36SAndroid Build Coastguard Worker	Avb_private_key *string `android:"path_device_first"`
95*333d2b36SAndroid Build Coastguard Worker
96*333d2b36SAndroid Build Coastguard Worker	// Hash and signing algorithm for avbtool. Default is SHA256_RSA4096.
97*333d2b36SAndroid Build Coastguard Worker	Avb_algorithm *string
98*333d2b36SAndroid Build Coastguard Worker
99*333d2b36SAndroid Build Coastguard Worker	// The index used to prevent rollback of the image on device.
100*333d2b36SAndroid Build Coastguard Worker	Avb_rollback_index *int64
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Worker	// The security patch passed to as the com.android.build.<type>.security_patch avb property.
103*333d2b36SAndroid Build Coastguard Worker	// Replacement for the make variables BOOT_SECURITY_PATCH / INIT_BOOT_SECURITY_PATCH.
104*333d2b36SAndroid Build Coastguard Worker	Security_patch *string
105*333d2b36SAndroid Build Coastguard Worker}
106*333d2b36SAndroid Build Coastguard Worker
107*333d2b36SAndroid Build Coastguard Workertype bootImageType int
108*333d2b36SAndroid Build Coastguard Worker
109*333d2b36SAndroid Build Coastguard Workerconst (
110*333d2b36SAndroid Build Coastguard Worker	unsupported bootImageType = iota
111*333d2b36SAndroid Build Coastguard Worker	boot
112*333d2b36SAndroid Build Coastguard Worker	vendorBoot
113*333d2b36SAndroid Build Coastguard Worker	initBoot
114*333d2b36SAndroid Build Coastguard Worker)
115*333d2b36SAndroid Build Coastguard Worker
116*333d2b36SAndroid Build Coastguard Workerfunc toBootImageType(ctx android.ModuleContext, bootImageType string) bootImageType {
117*333d2b36SAndroid Build Coastguard Worker	switch bootImageType {
118*333d2b36SAndroid Build Coastguard Worker	case "boot":
119*333d2b36SAndroid Build Coastguard Worker		return boot
120*333d2b36SAndroid Build Coastguard Worker	case "vendor_boot":
121*333d2b36SAndroid Build Coastguard Worker		return vendorBoot
122*333d2b36SAndroid Build Coastguard Worker	case "init_boot":
123*333d2b36SAndroid Build Coastguard Worker		return initBoot
124*333d2b36SAndroid Build Coastguard Worker	default:
125*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("Unknown boot_image_type %s. Must be one of \"boot\", \"vendor_boot\", or \"init_boot\"", bootImageType)
126*333d2b36SAndroid Build Coastguard Worker	}
127*333d2b36SAndroid Build Coastguard Worker	return unsupported
128*333d2b36SAndroid Build Coastguard Worker}
129*333d2b36SAndroid Build Coastguard Worker
130*333d2b36SAndroid Build Coastguard Workerfunc (b bootImageType) String() string {
131*333d2b36SAndroid Build Coastguard Worker	switch b {
132*333d2b36SAndroid Build Coastguard Worker	case boot:
133*333d2b36SAndroid Build Coastguard Worker		return "boot"
134*333d2b36SAndroid Build Coastguard Worker	case vendorBoot:
135*333d2b36SAndroid Build Coastguard Worker		return "vendor_boot"
136*333d2b36SAndroid Build Coastguard Worker	case initBoot:
137*333d2b36SAndroid Build Coastguard Worker		return "init_boot"
138*333d2b36SAndroid Build Coastguard Worker	default:
139*333d2b36SAndroid Build Coastguard Worker		panic("unknown boot image type")
140*333d2b36SAndroid Build Coastguard Worker	}
141*333d2b36SAndroid Build Coastguard Worker}
142*333d2b36SAndroid Build Coastguard Worker
143*333d2b36SAndroid Build Coastguard Workerfunc (b bootImageType) isBoot() bool {
144*333d2b36SAndroid Build Coastguard Worker	return b == boot
145*333d2b36SAndroid Build Coastguard Worker}
146*333d2b36SAndroid Build Coastguard Worker
147*333d2b36SAndroid Build Coastguard Workerfunc (b bootImageType) isVendorBoot() bool {
148*333d2b36SAndroid Build Coastguard Worker	return b == vendorBoot
149*333d2b36SAndroid Build Coastguard Worker}
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Workerfunc (b bootImageType) isInitBoot() bool {
152*333d2b36SAndroid Build Coastguard Worker	return b == initBoot
153*333d2b36SAndroid Build Coastguard Worker}
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker// bootimg is the image for the boot partition. It consists of header, kernel, ramdisk, and dtb.
156*333d2b36SAndroid Build Coastguard Workerfunc BootimgFactory() android.Module {
157*333d2b36SAndroid Build Coastguard Worker	module := &bootimg{}
158*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
159*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
160*333d2b36SAndroid Build Coastguard Worker	return module
161*333d2b36SAndroid Build Coastguard Worker}
162*333d2b36SAndroid Build Coastguard Worker
163*333d2b36SAndroid Build Coastguard Workertype bootimgDep struct {
164*333d2b36SAndroid Build Coastguard Worker	blueprint.BaseDependencyTag
165*333d2b36SAndroid Build Coastguard Worker	kind string
166*333d2b36SAndroid Build Coastguard Worker}
167*333d2b36SAndroid Build Coastguard Worker
168*333d2b36SAndroid Build Coastguard Workervar bootimgRamdiskDep = bootimgDep{kind: "ramdisk"}
169*333d2b36SAndroid Build Coastguard Worker
170*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) DepsMutator(ctx android.BottomUpMutatorContext) {
171*333d2b36SAndroid Build Coastguard Worker	ramdisk := proptools.String(b.properties.Ramdisk_module)
172*333d2b36SAndroid Build Coastguard Worker	if ramdisk != "" {
173*333d2b36SAndroid Build Coastguard Worker		ctx.AddDependency(ctx.Module(), bootimgRamdiskDep, ramdisk)
174*333d2b36SAndroid Build Coastguard Worker	}
175*333d2b36SAndroid Build Coastguard Worker}
176*333d2b36SAndroid Build Coastguard Worker
177*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) installFileName() string {
178*333d2b36SAndroid Build Coastguard Worker	return proptools.StringDefault(b.properties.Stem, b.BaseModuleName()+".img")
179*333d2b36SAndroid Build Coastguard Worker}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) partitionName() string {
182*333d2b36SAndroid Build Coastguard Worker	return proptools.StringDefault(b.properties.Partition_name, b.BaseModuleName())
183*333d2b36SAndroid Build Coastguard Worker}
184*333d2b36SAndroid Build Coastguard Worker
185*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
186*333d2b36SAndroid Build Coastguard Worker	b.bootImageType = toBootImageType(ctx, proptools.StringDefault(b.properties.Boot_image_type, "boot"))
187*333d2b36SAndroid Build Coastguard Worker	if b.bootImageType == unsupported {
188*333d2b36SAndroid Build Coastguard Worker		return
189*333d2b36SAndroid Build Coastguard Worker	}
190*333d2b36SAndroid Build Coastguard Worker
191*333d2b36SAndroid Build Coastguard Worker	kernelProp := proptools.String(b.properties.Kernel_prebuilt)
192*333d2b36SAndroid Build Coastguard Worker	if b.bootImageType.isVendorBoot() && kernelProp != "" {
193*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel")
194*333d2b36SAndroid Build Coastguard Worker		return
195*333d2b36SAndroid Build Coastguard Worker	}
196*333d2b36SAndroid Build Coastguard Worker	if b.bootImageType.isBoot() && kernelProp == "" {
197*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel")
198*333d2b36SAndroid Build Coastguard Worker		return
199*333d2b36SAndroid Build Coastguard Worker	}
200*333d2b36SAndroid Build Coastguard Worker	var kernel android.Path
201*333d2b36SAndroid Build Coastguard Worker	if kernelProp != "" {
202*333d2b36SAndroid Build Coastguard Worker		kernel = android.PathForModuleSrc(ctx, kernelProp)
203*333d2b36SAndroid Build Coastguard Worker	}
204*333d2b36SAndroid Build Coastguard Worker
205*333d2b36SAndroid Build Coastguard Worker	unsignedOutput := b.buildBootImage(ctx, kernel)
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker	output := unsignedOutput
208*333d2b36SAndroid Build Coastguard Worker	if proptools.Bool(b.properties.Use_avb) {
209*333d2b36SAndroid Build Coastguard Worker		// This bootimg module supports 2 modes of avb signing. It is not clear to this author
210*333d2b36SAndroid Build Coastguard Worker		// why there are differences, but one of them is to match the behavior of make-built boot
211*333d2b36SAndroid Build Coastguard Worker		// images.
212*333d2b36SAndroid Build Coastguard Worker		switch proptools.StringDefault(b.properties.Avb_mode, "default") {
213*333d2b36SAndroid Build Coastguard Worker		case "default":
214*333d2b36SAndroid Build Coastguard Worker			output = b.signImage(ctx, unsignedOutput)
215*333d2b36SAndroid Build Coastguard Worker		case "make_legacy":
216*333d2b36SAndroid Build Coastguard Worker			output = b.addAvbFooter(ctx, unsignedOutput, kernel)
217*333d2b36SAndroid Build Coastguard Worker		default:
218*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("avb_mode", `Unknown value for avb_mode, expected "default" or "make_legacy", got: %q`, *b.properties.Avb_mode)
219*333d2b36SAndroid Build Coastguard Worker		}
220*333d2b36SAndroid Build Coastguard Worker	}
221*333d2b36SAndroid Build Coastguard Worker
222*333d2b36SAndroid Build Coastguard Worker	b.installDir = android.PathForModuleInstall(ctx, "etc")
223*333d2b36SAndroid Build Coastguard Worker	ctx.InstallFile(b.installDir, b.installFileName(), output)
224*333d2b36SAndroid Build Coastguard Worker
225*333d2b36SAndroid Build Coastguard Worker	ctx.SetOutputFiles([]android.Path{output}, "")
226*333d2b36SAndroid Build Coastguard Worker	b.output = output
227*333d2b36SAndroid Build Coastguard Worker}
228*333d2b36SAndroid Build Coastguard Worker
229*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) buildBootImage(ctx android.ModuleContext, kernel android.Path) android.Path {
230*333d2b36SAndroid Build Coastguard Worker	output := android.PathForModuleOut(ctx, "unsigned", b.installFileName())
231*333d2b36SAndroid Build Coastguard Worker
232*333d2b36SAndroid Build Coastguard Worker	builder := android.NewRuleBuilder(pctx, ctx)
233*333d2b36SAndroid Build Coastguard Worker	cmd := builder.Command().BuiltTool("mkbootimg")
234*333d2b36SAndroid Build Coastguard Worker
235*333d2b36SAndroid Build Coastguard Worker	if kernel != nil {
236*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithInput("--kernel ", kernel)
237*333d2b36SAndroid Build Coastguard Worker	}
238*333d2b36SAndroid Build Coastguard Worker
239*333d2b36SAndroid Build Coastguard Worker	// These arguments are passed for boot.img and init_boot.img generation
240*333d2b36SAndroid Build Coastguard Worker	if b.bootImageType.isBoot() || b.bootImageType.isInitBoot() {
241*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--os_version ", ctx.Config().PlatformVersionLastStable())
242*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--os_patch_level ", ctx.Config().PlatformSecurityPatch())
243*333d2b36SAndroid Build Coastguard Worker	}
244*333d2b36SAndroid Build Coastguard Worker
245*333d2b36SAndroid Build Coastguard Worker	dtbName := proptools.String(b.properties.Dtb_prebuilt)
246*333d2b36SAndroid Build Coastguard Worker	if dtbName != "" {
247*333d2b36SAndroid Build Coastguard Worker		dtb := android.PathForModuleSrc(ctx, dtbName)
248*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithInput("--dtb ", dtb)
249*333d2b36SAndroid Build Coastguard Worker	}
250*333d2b36SAndroid Build Coastguard Worker
251*333d2b36SAndroid Build Coastguard Worker	cmdline := strings.Join(b.properties.Cmdline, " ")
252*333d2b36SAndroid Build Coastguard Worker	if cmdline != "" {
253*333d2b36SAndroid Build Coastguard Worker		flag := "--cmdline "
254*333d2b36SAndroid Build Coastguard Worker		if b.bootImageType.isVendorBoot() {
255*333d2b36SAndroid Build Coastguard Worker			flag = "--vendor_cmdline "
256*333d2b36SAndroid Build Coastguard Worker		}
257*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg(flag, proptools.ShellEscapeIncludingSpaces(cmdline))
258*333d2b36SAndroid Build Coastguard Worker	}
259*333d2b36SAndroid Build Coastguard Worker
260*333d2b36SAndroid Build Coastguard Worker	headerVersion := proptools.String(b.properties.Header_version)
261*333d2b36SAndroid Build Coastguard Worker	if headerVersion == "" {
262*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("header_version", "must be set")
263*333d2b36SAndroid Build Coastguard Worker		return output
264*333d2b36SAndroid Build Coastguard Worker	}
265*333d2b36SAndroid Build Coastguard Worker	verNum, err := strconv.Atoi(headerVersion)
266*333d2b36SAndroid Build Coastguard Worker	if err != nil {
267*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("header_version", "%q is not a number", headerVersion)
268*333d2b36SAndroid Build Coastguard Worker		return output
269*333d2b36SAndroid Build Coastguard Worker	}
270*333d2b36SAndroid Build Coastguard Worker	if verNum < 3 {
271*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("header_version", "must be 3 or higher for vendor_boot")
272*333d2b36SAndroid Build Coastguard Worker		return output
273*333d2b36SAndroid Build Coastguard Worker	}
274*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithArg("--header_version ", headerVersion)
275*333d2b36SAndroid Build Coastguard Worker
276*333d2b36SAndroid Build Coastguard Worker	ramdiskName := proptools.String(b.properties.Ramdisk_module)
277*333d2b36SAndroid Build Coastguard Worker	if ramdiskName != "" {
278*333d2b36SAndroid Build Coastguard Worker		ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep)
279*333d2b36SAndroid Build Coastguard Worker		if filesystem, ok := ramdisk.(*filesystem); ok {
280*333d2b36SAndroid Build Coastguard Worker			flag := "--ramdisk "
281*333d2b36SAndroid Build Coastguard Worker			if b.bootImageType.isVendorBoot() {
282*333d2b36SAndroid Build Coastguard Worker				flag = "--vendor_ramdisk "
283*333d2b36SAndroid Build Coastguard Worker			}
284*333d2b36SAndroid Build Coastguard Worker			cmd.FlagWithInput(flag, filesystem.OutputPath())
285*333d2b36SAndroid Build Coastguard Worker		} else {
286*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("ramdisk", "%q is not android_filesystem module", ramdisk.Name())
287*333d2b36SAndroid Build Coastguard Worker			return output
288*333d2b36SAndroid Build Coastguard Worker		}
289*333d2b36SAndroid Build Coastguard Worker	}
290*333d2b36SAndroid Build Coastguard Worker
291*333d2b36SAndroid Build Coastguard Worker	bootconfig := proptools.String(b.properties.Bootconfig)
292*333d2b36SAndroid Build Coastguard Worker	if bootconfig != "" {
293*333d2b36SAndroid Build Coastguard Worker		if !b.bootImageType.isVendorBoot() {
294*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("bootconfig", "requires vendor_boot: true")
295*333d2b36SAndroid Build Coastguard Worker			return output
296*333d2b36SAndroid Build Coastguard Worker		}
297*333d2b36SAndroid Build Coastguard Worker		if verNum < 4 {
298*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("bootconfig", "requires header_version: 4 or later")
299*333d2b36SAndroid Build Coastguard Worker			return output
300*333d2b36SAndroid Build Coastguard Worker		}
301*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithInput("--vendor_bootconfig ", android.PathForModuleSrc(ctx, bootconfig))
302*333d2b36SAndroid Build Coastguard Worker	}
303*333d2b36SAndroid Build Coastguard Worker
304*333d2b36SAndroid Build Coastguard Worker	// Output flag for boot.img and init_boot.img
305*333d2b36SAndroid Build Coastguard Worker	flag := "--output "
306*333d2b36SAndroid Build Coastguard Worker	if b.bootImageType.isVendorBoot() {
307*333d2b36SAndroid Build Coastguard Worker		flag = "--vendor_boot "
308*333d2b36SAndroid Build Coastguard Worker	}
309*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithOutput(flag, output)
310*333d2b36SAndroid Build Coastguard Worker
311*333d2b36SAndroid Build Coastguard Worker	if b.properties.Partition_size != nil {
312*333d2b36SAndroid Build Coastguard Worker		assertMaxImageSize(builder, output, *b.properties.Partition_size, proptools.Bool(b.properties.Use_avb))
313*333d2b36SAndroid Build Coastguard Worker	}
314*333d2b36SAndroid Build Coastguard Worker
315*333d2b36SAndroid Build Coastguard Worker	builder.Build("build_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
316*333d2b36SAndroid Build Coastguard Worker	return output
317*333d2b36SAndroid Build Coastguard Worker}
318*333d2b36SAndroid Build Coastguard Worker
319*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) addAvbFooter(ctx android.ModuleContext, unsignedImage android.Path, kernel android.Path) android.Path {
320*333d2b36SAndroid Build Coastguard Worker	output := android.PathForModuleOut(ctx, b.installFileName())
321*333d2b36SAndroid Build Coastguard Worker	builder := android.NewRuleBuilder(pctx, ctx)
322*333d2b36SAndroid Build Coastguard Worker	builder.Command().Text("cp").Input(unsignedImage).Output(output)
323*333d2b36SAndroid Build Coastguard Worker	cmd := builder.Command().BuiltTool("avbtool").
324*333d2b36SAndroid Build Coastguard Worker		Text("add_hash_footer").
325*333d2b36SAndroid Build Coastguard Worker		FlagWithInput("--image ", output)
326*333d2b36SAndroid Build Coastguard Worker
327*333d2b36SAndroid Build Coastguard Worker	if b.properties.Partition_size != nil {
328*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--partition_size ", strconv.FormatInt(*b.properties.Partition_size, 10))
329*333d2b36SAndroid Build Coastguard Worker	} else {
330*333d2b36SAndroid Build Coastguard Worker		cmd.Flag("--dynamic_partition_size")
331*333d2b36SAndroid Build Coastguard Worker	}
332*333d2b36SAndroid Build Coastguard Worker
333*333d2b36SAndroid Build Coastguard Worker	// If you don't provide a salt, avbtool will use random bytes for the salt.
334*333d2b36SAndroid Build Coastguard Worker	// This is bad for determinism (cached builds and diff tests are affected), so instead,
335*333d2b36SAndroid Build Coastguard Worker	// we try to provide a salt. The requirements for a salt are not very clear, one aspect of it
336*333d2b36SAndroid Build Coastguard Worker	// is that if it's unpredictable, attackers trying to change the contents of a partition need
337*333d2b36SAndroid Build Coastguard Worker	// to find a new hash collision every release, because the salt changed.
338*333d2b36SAndroid Build Coastguard Worker	if kernel != nil {
339*333d2b36SAndroid Build Coastguard Worker		cmd.Textf(`--salt $(sha256sum "%s" | cut -d " " -f 1)`, kernel.String())
340*333d2b36SAndroid Build Coastguard Worker		cmd.Implicit(kernel)
341*333d2b36SAndroid Build Coastguard Worker	} else {
342*333d2b36SAndroid Build Coastguard Worker		cmd.Textf(`--salt $(sha256sum "%s" "%s" | cut -d " " -f 1 | tr -d '\n')`, ctx.Config().BuildNumberFile(ctx), ctx.Config().Getenv("BUILD_DATETIME_FILE"))
343*333d2b36SAndroid Build Coastguard Worker		cmd.OrderOnly(ctx.Config().BuildNumberFile(ctx))
344*333d2b36SAndroid Build Coastguard Worker	}
345*333d2b36SAndroid Build Coastguard Worker
346*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithArg("--partition_name ", b.bootImageType.String())
347*333d2b36SAndroid Build Coastguard Worker
348*333d2b36SAndroid Build Coastguard Worker	if b.properties.Avb_algorithm != nil {
349*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--algorithm ", proptools.NinjaAndShellEscape(*b.properties.Avb_algorithm))
350*333d2b36SAndroid Build Coastguard Worker	}
351*333d2b36SAndroid Build Coastguard Worker
352*333d2b36SAndroid Build Coastguard Worker	if b.properties.Avb_private_key != nil {
353*333d2b36SAndroid Build Coastguard Worker		key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
354*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithInput("--key ", key)
355*333d2b36SAndroid Build Coastguard Worker	}
356*333d2b36SAndroid Build Coastguard Worker
357*333d2b36SAndroid Build Coastguard Worker	if !b.bootImageType.isVendorBoot() {
358*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--prop ", proptools.NinjaAndShellEscape(fmt.Sprintf(
359*333d2b36SAndroid Build Coastguard Worker			"com.android.build.%s.os_version:%s", b.bootImageType.String(), ctx.Config().PlatformVersionLastStable())))
360*333d2b36SAndroid Build Coastguard Worker	}
361*333d2b36SAndroid Build Coastguard Worker
362*333d2b36SAndroid Build Coastguard Worker	fingerprintFile := ctx.Config().BuildFingerprintFile(ctx)
363*333d2b36SAndroid Build Coastguard Worker	cmd.FlagWithArg("--prop ", fmt.Sprintf("com.android.build.%s.fingerprint:$(cat %s)", b.bootImageType.String(), fingerprintFile.String()))
364*333d2b36SAndroid Build Coastguard Worker	cmd.OrderOnly(fingerprintFile)
365*333d2b36SAndroid Build Coastguard Worker
366*333d2b36SAndroid Build Coastguard Worker	if b.properties.Security_patch != nil {
367*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--prop ", proptools.NinjaAndShellEscape(fmt.Sprintf(
368*333d2b36SAndroid Build Coastguard Worker			"com.android.build.%s.security_patch:%s", b.bootImageType.String(), *b.properties.Security_patch)))
369*333d2b36SAndroid Build Coastguard Worker	}
370*333d2b36SAndroid Build Coastguard Worker
371*333d2b36SAndroid Build Coastguard Worker	if b.properties.Avb_rollback_index != nil {
372*333d2b36SAndroid Build Coastguard Worker		cmd.FlagWithArg("--rollback_index ", strconv.FormatInt(*b.properties.Avb_rollback_index, 10))
373*333d2b36SAndroid Build Coastguard Worker	}
374*333d2b36SAndroid Build Coastguard Worker
375*333d2b36SAndroid Build Coastguard Worker	builder.Build("add_avb_footer", fmt.Sprintf("Adding avb footer to %s", b.BaseModuleName()))
376*333d2b36SAndroid Build Coastguard Worker	return output
377*333d2b36SAndroid Build Coastguard Worker}
378*333d2b36SAndroid Build Coastguard Worker
379*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) signImage(ctx android.ModuleContext, unsignedImage android.Path) android.Path {
380*333d2b36SAndroid Build Coastguard Worker	propFile, toolDeps := b.buildPropFile(ctx)
381*333d2b36SAndroid Build Coastguard Worker
382*333d2b36SAndroid Build Coastguard Worker	output := android.PathForModuleOut(ctx, b.installFileName())
383*333d2b36SAndroid Build Coastguard Worker	builder := android.NewRuleBuilder(pctx, ctx)
384*333d2b36SAndroid Build Coastguard Worker	builder.Command().Text("cp").Input(unsignedImage).Output(output)
385*333d2b36SAndroid Build Coastguard Worker	builder.Command().BuiltTool("verity_utils").
386*333d2b36SAndroid Build Coastguard Worker		Input(propFile).
387*333d2b36SAndroid Build Coastguard Worker		Implicits(toolDeps).
388*333d2b36SAndroid Build Coastguard Worker		Output(output)
389*333d2b36SAndroid Build Coastguard Worker
390*333d2b36SAndroid Build Coastguard Worker	builder.Build("sign_bootimg", fmt.Sprintf("Signing %s", b.BaseModuleName()))
391*333d2b36SAndroid Build Coastguard Worker	return output
392*333d2b36SAndroid Build Coastguard Worker}
393*333d2b36SAndroid Build Coastguard Worker
394*333d2b36SAndroid Build Coastguard Worker// Calculates avb_salt from some input for deterministic output.
395*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) salt() string {
396*333d2b36SAndroid Build Coastguard Worker	var input []string
397*333d2b36SAndroid Build Coastguard Worker	input = append(input, b.properties.Cmdline...)
398*333d2b36SAndroid Build Coastguard Worker	input = append(input, proptools.StringDefault(b.properties.Partition_name, b.Name()))
399*333d2b36SAndroid Build Coastguard Worker	input = append(input, proptools.String(b.properties.Header_version))
400*333d2b36SAndroid Build Coastguard Worker	return sha1sum(input)
401*333d2b36SAndroid Build Coastguard Worker}
402*333d2b36SAndroid Build Coastguard Worker
403*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) buildPropFile(ctx android.ModuleContext) (android.Path, android.Paths) {
404*333d2b36SAndroid Build Coastguard Worker	var sb strings.Builder
405*333d2b36SAndroid Build Coastguard Worker	var deps android.Paths
406*333d2b36SAndroid Build Coastguard Worker	addStr := func(name string, value string) {
407*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintf(&sb, "%s=%s\n", name, value)
408*333d2b36SAndroid Build Coastguard Worker	}
409*333d2b36SAndroid Build Coastguard Worker	addPath := func(name string, path android.Path) {
410*333d2b36SAndroid Build Coastguard Worker		addStr(name, path.String())
411*333d2b36SAndroid Build Coastguard Worker		deps = append(deps, path)
412*333d2b36SAndroid Build Coastguard Worker	}
413*333d2b36SAndroid Build Coastguard Worker
414*333d2b36SAndroid Build Coastguard Worker	addStr("avb_hash_enable", "true")
415*333d2b36SAndroid Build Coastguard Worker	addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool"))
416*333d2b36SAndroid Build Coastguard Worker	algorithm := proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096")
417*333d2b36SAndroid Build Coastguard Worker	addStr("avb_algorithm", algorithm)
418*333d2b36SAndroid Build Coastguard Worker	key := android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key))
419*333d2b36SAndroid Build Coastguard Worker	addPath("avb_key_path", key)
420*333d2b36SAndroid Build Coastguard Worker	addStr("avb_add_hash_footer_args", "") // TODO(jiyong): add --rollback_index
421*333d2b36SAndroid Build Coastguard Worker	partitionName := proptools.StringDefault(b.properties.Partition_name, b.Name())
422*333d2b36SAndroid Build Coastguard Worker	addStr("partition_name", partitionName)
423*333d2b36SAndroid Build Coastguard Worker	addStr("avb_salt", b.salt())
424*333d2b36SAndroid Build Coastguard Worker
425*333d2b36SAndroid Build Coastguard Worker	propFile := android.PathForModuleOut(ctx, "prop")
426*333d2b36SAndroid Build Coastguard Worker	android.WriteFileRule(ctx, propFile, sb.String())
427*333d2b36SAndroid Build Coastguard Worker	return propFile, deps
428*333d2b36SAndroid Build Coastguard Worker}
429*333d2b36SAndroid Build Coastguard Worker
430*333d2b36SAndroid Build Coastguard Workervar _ android.AndroidMkEntriesProvider = (*bootimg)(nil)
431*333d2b36SAndroid Build Coastguard Worker
432*333d2b36SAndroid Build Coastguard Worker// Implements android.AndroidMkEntriesProvider
433*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) AndroidMkEntries() []android.AndroidMkEntries {
434*333d2b36SAndroid Build Coastguard Worker	return []android.AndroidMkEntries{android.AndroidMkEntries{
435*333d2b36SAndroid Build Coastguard Worker		Class:      "ETC",
436*333d2b36SAndroid Build Coastguard Worker		OutputFile: android.OptionalPathForPath(b.output),
437*333d2b36SAndroid Build Coastguard Worker		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
438*333d2b36SAndroid Build Coastguard Worker			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
439*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_MODULE_PATH", b.installDir.String())
440*333d2b36SAndroid Build Coastguard Worker				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", b.installFileName())
441*333d2b36SAndroid Build Coastguard Worker			},
442*333d2b36SAndroid Build Coastguard Worker		},
443*333d2b36SAndroid Build Coastguard Worker	}}
444*333d2b36SAndroid Build Coastguard Worker}
445*333d2b36SAndroid Build Coastguard Worker
446*333d2b36SAndroid Build Coastguard Workervar _ Filesystem = (*bootimg)(nil)
447*333d2b36SAndroid Build Coastguard Worker
448*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) OutputPath() android.Path {
449*333d2b36SAndroid Build Coastguard Worker	return b.output
450*333d2b36SAndroid Build Coastguard Worker}
451*333d2b36SAndroid Build Coastguard Worker
452*333d2b36SAndroid Build Coastguard Workerfunc (b *bootimg) SignedOutputPath() android.Path {
453*333d2b36SAndroid Build Coastguard Worker	if proptools.Bool(b.properties.Use_avb) {
454*333d2b36SAndroid Build Coastguard Worker		return b.OutputPath()
455*333d2b36SAndroid Build Coastguard Worker	}
456*333d2b36SAndroid Build Coastguard Worker	return nil
457*333d2b36SAndroid Build Coastguard Worker}
458