xref: /aosp_15_r20/build/soong/fsgen/boot_imgs.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1package fsgen
2
3import (
4	"android/soong/android"
5	"android/soong/filesystem"
6	"fmt"
7	"path/filepath"
8	"strconv"
9	"strings"
10
11	"github.com/google/blueprint/proptools"
12)
13
14func createBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool {
15	partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
16
17	if partitionVariables.TargetKernelPath == "" {
18		// There are potentially code paths that don't set TARGET_KERNEL_PATH
19		return false
20	}
21
22	kernelDir := filepath.Dir(partitionVariables.TargetKernelPath)
23	kernelBase := filepath.Base(partitionVariables.TargetKernelPath)
24	kernelFilegroupName := generatedModuleName(ctx.Config(), "kernel")
25
26	ctx.CreateModuleInDirectory(
27		android.FileGroupFactory,
28		kernelDir,
29		&struct {
30			Name       *string
31			Srcs       []string
32			Visibility []string
33		}{
34			Name:       proptools.StringPtr(kernelFilegroupName),
35			Srcs:       []string{kernelBase},
36			Visibility: []string{"//visibility:public"},
37		},
38	)
39
40	var partitionSize *int64
41	if partitionVariables.BoardBootimagePartitionSize != "" {
42		// Base of zero will allow base 10 or base 16 if starting with 0x
43		parsed, err := strconv.ParseInt(partitionVariables.BoardBootimagePartitionSize, 0, 64)
44		if err != nil {
45			panic(fmt.Sprintf("BOARD_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardBootimagePartitionSize))
46		}
47		partitionSize = &parsed
48	}
49
50	var securityPatch *string
51	if partitionVariables.BootSecurityPatch != "" {
52		securityPatch = &partitionVariables.BootSecurityPatch
53	}
54
55	avbInfo := getAvbInfo(ctx.Config(), "boot")
56
57	bootImageName := generatedModuleNameForPartition(ctx.Config(), "boot")
58
59	var dtbPrebuilt *string
60	if dtbImg.include && dtbImg.imgType == "boot" {
61		dtbPrebuilt = proptools.StringPtr(":" + dtbImg.name)
62	}
63
64	var cmdline []string
65	if !buildingVendorBootImage(partitionVariables) {
66		cmdline = partitionVariables.InternalKernelCmdline
67	}
68
69	ctx.CreateModule(
70		filesystem.BootimgFactory,
71		&filesystem.BootimgProperties{
72			Kernel_prebuilt:    proptools.StringPtr(":" + kernelFilegroupName),
73			Header_version:     proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
74			Partition_size:     partitionSize,
75			Use_avb:            avbInfo.avbEnable,
76			Avb_mode:           avbInfo.avbMode,
77			Avb_private_key:    avbInfo.avbkeyFilegroup,
78			Avb_rollback_index: avbInfo.avbRollbackIndex,
79			Avb_algorithm:      avbInfo.avbAlgorithm,
80			Security_patch:     securityPatch,
81			Dtb_prebuilt:       dtbPrebuilt,
82			Cmdline:            cmdline,
83		},
84		&struct {
85			Name *string
86		}{
87			Name: proptools.StringPtr(bootImageName),
88		},
89	)
90	return true
91}
92
93func createVendorBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool {
94	partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
95
96	bootImageName := generatedModuleNameForPartition(ctx.Config(), "vendor_boot")
97
98	avbInfo := getAvbInfo(ctx.Config(), "vendor_boot")
99
100	var dtbPrebuilt *string
101	if dtbImg.include && dtbImg.imgType == "vendor_boot" {
102		dtbPrebuilt = proptools.StringPtr(":" + dtbImg.name)
103	}
104
105	cmdline := partitionVariables.InternalKernelCmdline
106
107	var vendorBootConfigImg *string
108	if name, ok := createVendorBootConfigImg(ctx); ok {
109		vendorBootConfigImg = proptools.StringPtr(":" + name)
110	}
111
112	ctx.CreateModule(
113		filesystem.BootimgFactory,
114		&filesystem.BootimgProperties{
115			Boot_image_type:    proptools.StringPtr("vendor_boot"),
116			Ramdisk_module:     proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")),
117			Header_version:     proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
118			Use_avb:            avbInfo.avbEnable,
119			Avb_mode:           avbInfo.avbMode,
120			Avb_private_key:    avbInfo.avbkeyFilegroup,
121			Avb_rollback_index: avbInfo.avbRollbackIndex,
122			Avb_algorithm:      avbInfo.avbAlgorithm,
123			Dtb_prebuilt:       dtbPrebuilt,
124			Cmdline:            cmdline,
125			Bootconfig:         vendorBootConfigImg,
126		},
127		&struct {
128			Name *string
129		}{
130			Name: proptools.StringPtr(bootImageName),
131		},
132	)
133	return true
134}
135
136func createInitBootImage(ctx android.LoadHookContext) bool {
137	partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
138
139	bootImageName := generatedModuleNameForPartition(ctx.Config(), "init_boot")
140
141	var securityPatch *string
142	if partitionVariables.InitBootSecurityPatch != "" {
143		securityPatch = &partitionVariables.InitBootSecurityPatch
144	} else if partitionVariables.BootSecurityPatch != "" {
145		securityPatch = &partitionVariables.BootSecurityPatch
146	}
147
148	var partitionSize *int64
149	if partitionVariables.BoardInitBootimagePartitionSize != "" {
150		// Base of zero will allow base 10 or base 16 if starting with 0x
151		parsed, err := strconv.ParseInt(partitionVariables.BoardInitBootimagePartitionSize, 0, 64)
152		if err != nil {
153			panic(fmt.Sprintf("BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardInitBootimagePartitionSize))
154		}
155		partitionSize = &parsed
156	}
157
158	avbInfo := getAvbInfo(ctx.Config(), "init_boot")
159
160	ctx.CreateModule(
161		filesystem.BootimgFactory,
162		&filesystem.BootimgProperties{
163			Boot_image_type:    proptools.StringPtr("init_boot"),
164			Ramdisk_module:     proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")),
165			Header_version:     proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
166			Security_patch:     securityPatch,
167			Partition_size:     partitionSize,
168			Use_avb:            avbInfo.avbEnable,
169			Avb_mode:           avbInfo.avbMode,
170			Avb_private_key:    avbInfo.avbkeyFilegroup,
171			Avb_rollback_index: avbInfo.avbRollbackIndex,
172			Avb_algorithm:      avbInfo.avbAlgorithm,
173		},
174		&struct {
175			Name *string
176		}{
177			Name: proptools.StringPtr(bootImageName),
178		},
179	)
180	return true
181}
182
183// Returns the equivalent of the BUILDING_BOOT_IMAGE variable in make. Derived from this logic:
184// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=458;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
185func buildingBootImage(partitionVars android.PartitionVariables) bool {
186	if partitionVars.BoardUsesRecoveryAsBoot {
187		return false
188	}
189
190	if partitionVars.ProductBuildBootImage {
191		return true
192	}
193
194	if len(partitionVars.BoardPrebuiltBootimage) > 0 {
195		return false
196	}
197
198	if len(partitionVars.BoardBootimagePartitionSize) > 0 {
199		return true
200	}
201
202	// TODO: return true if BOARD_KERNEL_BINARIES is set and has a *_BOOTIMAGE_PARTITION_SIZE
203	// variable. However, I don't think BOARD_KERNEL_BINARIES is ever set in practice.
204
205	return false
206}
207
208// Returns the equivalent of the BUILDING_VENDOR_BOOT_IMAGE variable in make. Derived from this logic:
209// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=518;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
210func buildingVendorBootImage(partitionVars android.PartitionVariables) bool {
211	if v, exists := boardBootHeaderVersion(partitionVars); exists && v >= 3 {
212		x := partitionVars.ProductBuildVendorBootImage
213		if x == "" || x == "true" {
214			return true
215		}
216	}
217
218	return false
219}
220
221// Derived from: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=480;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
222func buildingInitBootImage(partitionVars android.PartitionVariables) bool {
223	if !partitionVars.ProductBuildInitBootImage {
224		if partitionVars.BoardUsesRecoveryAsBoot || len(partitionVars.BoardPrebuiltInitBootimage) > 0 {
225			return false
226		} else if len(partitionVars.BoardInitBootimagePartitionSize) > 0 {
227			return true
228		}
229	} else {
230		if partitionVars.BoardUsesRecoveryAsBoot {
231			panic("PRODUCT_BUILD_INIT_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT. Use only one option.")
232		}
233		return true
234	}
235	return false
236}
237
238func boardBootHeaderVersion(partitionVars android.PartitionVariables) (int, bool) {
239	if len(partitionVars.BoardBootHeaderVersion) == 0 {
240		return 0, false
241	}
242	v, err := strconv.ParseInt(partitionVars.BoardBootHeaderVersion, 10, 32)
243	if err != nil {
244		panic(fmt.Sprintf("BOARD_BOOT_HEADER_VERSION must be an int, got: %q", partitionVars.BoardBootHeaderVersion))
245	}
246	return int(v), true
247}
248
249type dtbImg struct {
250	// whether to include the dtb image in boot image
251	include bool
252
253	// name of the generated dtb image filegroup name
254	name string
255
256	// type of the boot image that the dtb image argument should be specified
257	imgType string
258}
259
260func createDtbImgFilegroup(ctx android.LoadHookContext) dtbImg {
261	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
262	if !partitionVars.BoardIncludeDtbInBootimg {
263		return dtbImg{include: false}
264	}
265	for _, copyFilePair := range partitionVars.ProductCopyFiles {
266		srcDestList := strings.Split(copyFilePair, ":")
267		if len(srcDestList) < 2 {
268			ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair)
269		}
270		if srcDestList[1] == "dtb.img" {
271			moduleName := generatedModuleName(ctx.Config(), "dtb_img_filegroup")
272			ctx.CreateModuleInDirectory(
273				android.FileGroupFactory,
274				filepath.Dir(srcDestList[0]),
275				&struct {
276					Name *string
277					Srcs []string
278				}{
279					Name: proptools.StringPtr(moduleName),
280					Srcs: []string{filepath.Base(srcDestList[1])},
281				},
282			)
283			imgType := "vendor_boot"
284			if !buildingVendorBootImage(partitionVars) {
285				imgType = "boot"
286			}
287			return dtbImg{include: true, name: moduleName, imgType: imgType}
288		}
289	}
290	return dtbImg{include: false}
291}
292
293func createVendorBootConfigImg(ctx android.LoadHookContext) (string, bool) {
294	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
295	bootconfig := partitionVars.InternalBootconfig
296	bootconfigFile := partitionVars.InternalBootconfigFile
297	if len(bootconfig) == 0 && len(bootconfigFile) == 0 {
298		return "", false
299	}
300
301	vendorBootconfigImgModuleName := generatedModuleName(ctx.Config(), "vendor_bootconfig_image")
302
303	ctx.CreateModule(
304		filesystem.BootconfigModuleFactory,
305		&struct {
306			Name             *string
307			Boot_config      []string
308			Boot_config_file *string
309		}{
310			Name:             proptools.StringPtr(vendorBootconfigImgModuleName),
311			Boot_config:      bootconfig,
312			Boot_config_file: proptools.StringPtr(bootconfigFile),
313		},
314	)
315
316	return vendorBootconfigImgModuleName, true
317}
318