• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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			Boot_image_type:             proptools.StringPtr("boot"),
73			Kernel_prebuilt:             proptools.StringPtr(":" + kernelFilegroupName),
74			Header_version:              proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
75			Partition_size:              partitionSize,
76			Use_avb:                     avbInfo.avbEnable,
77			Avb_mode:                    avbInfo.avbMode,
78			Avb_private_key:             avbInfo.avbkeyFilegroup,
79			Avb_rollback_index:          avbInfo.avbRollbackIndex,
80			Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
81			Avb_algorithm:               avbInfo.avbAlgorithm,
82			Security_patch:              securityPatch,
83			Dtb_prebuilt:                dtbPrebuilt,
84			Cmdline:                     cmdline,
85			Stem:                        proptools.StringPtr("boot.img"),
86		},
87		&struct {
88			Name       *string
89			Visibility []string
90		}{
91			Name:       proptools.StringPtr(bootImageName),
92			Visibility: []string{"//visibility:public"},
93		},
94	)
95	return true
96}
97
98func createVendorBootImage(ctx android.LoadHookContext, dtbImg dtbImg) bool {
99	partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
100
101	bootImageName := generatedModuleNameForPartition(ctx.Config(), "vendor_boot")
102
103	avbInfo := getAvbInfo(ctx.Config(), "vendor_boot")
104
105	var dtbPrebuilt *string
106	if dtbImg.include && dtbImg.imgType == "vendor_boot" {
107		dtbPrebuilt = proptools.StringPtr(":" + dtbImg.name)
108	}
109
110	cmdline := partitionVariables.InternalKernelCmdline
111
112	var vendorBootConfigImg *string
113	if name, ok := createVendorBootConfigImg(ctx); ok {
114		vendorBootConfigImg = proptools.StringPtr(":" + name)
115	}
116
117	var partitionSize *int64
118	if partitionVariables.BoardVendorBootimagePartitionSize != "" {
119		// Base of zero will allow base 10 or base 16 if starting with 0x
120		parsed, err := strconv.ParseInt(partitionVariables.BoardVendorBootimagePartitionSize, 0, 64)
121		if err != nil {
122			ctx.ModuleErrorf("BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardVendorBootimagePartitionSize)
123		}
124		partitionSize = &parsed
125	}
126
127	ctx.CreateModule(
128		filesystem.BootimgFactory,
129		&filesystem.BootimgProperties{
130			Boot_image_type:             proptools.StringPtr("vendor_boot"),
131			Ramdisk_module:              proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "vendor_ramdisk")),
132			Header_version:              proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
133			Partition_size:              partitionSize,
134			Use_avb:                     avbInfo.avbEnable,
135			Avb_mode:                    avbInfo.avbMode,
136			Avb_private_key:             avbInfo.avbkeyFilegroup,
137			Avb_rollback_index:          avbInfo.avbRollbackIndex,
138			Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
139			Dtb_prebuilt:                dtbPrebuilt,
140			Cmdline:                     cmdline,
141			Bootconfig:                  vendorBootConfigImg,
142			Stem:                        proptools.StringPtr("vendor_boot.img"),
143		},
144		&struct {
145			Name       *string
146			Visibility []string
147		}{
148			Name:       proptools.StringPtr(bootImageName),
149			Visibility: []string{"//visibility:public"},
150		},
151	)
152	return true
153}
154
155func createInitBootImage(ctx android.LoadHookContext) bool {
156	partitionVariables := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
157
158	bootImageName := generatedModuleNameForPartition(ctx.Config(), "init_boot")
159
160	var securityPatch *string
161	if partitionVariables.InitBootSecurityPatch != "" {
162		securityPatch = &partitionVariables.InitBootSecurityPatch
163	} else if partitionVariables.BootSecurityPatch != "" {
164		securityPatch = &partitionVariables.BootSecurityPatch
165	}
166
167	var partitionSize *int64
168	if partitionVariables.BoardInitBootimagePartitionSize != "" {
169		// Base of zero will allow base 10 or base 16 if starting with 0x
170		parsed, err := strconv.ParseInt(partitionVariables.BoardInitBootimagePartitionSize, 0, 64)
171		if err != nil {
172			panic(fmt.Sprintf("BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE must be an int, got %s", partitionVariables.BoardInitBootimagePartitionSize))
173		}
174		partitionSize = &parsed
175	}
176
177	avbInfo := getAvbInfo(ctx.Config(), "init_boot")
178
179	ctx.CreateModule(
180		filesystem.BootimgFactory,
181		&filesystem.BootimgProperties{
182			Boot_image_type:             proptools.StringPtr("init_boot"),
183			Ramdisk_module:              proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), "ramdisk")),
184			Header_version:              proptools.StringPtr(partitionVariables.BoardBootHeaderVersion),
185			Security_patch:              securityPatch,
186			Partition_size:              partitionSize,
187			Use_avb:                     avbInfo.avbEnable,
188			Avb_mode:                    avbInfo.avbMode,
189			Avb_private_key:             avbInfo.avbkeyFilegroup,
190			Avb_rollback_index:          avbInfo.avbRollbackIndex,
191			Avb_rollback_index_location: avbInfo.avbRollbackIndexLocation,
192			Avb_algorithm:               avbInfo.avbAlgorithm,
193			Stem:                        proptools.StringPtr("init_boot.img"),
194		},
195		&struct {
196			Name       *string
197			Visibility []string
198		}{
199			Name:       proptools.StringPtr(bootImageName),
200			Visibility: []string{"//visibility:public"},
201		},
202	)
203	return true
204}
205
206// Returns the equivalent of the BUILDING_BOOT_IMAGE variable in make. Derived from this logic:
207// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=458;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
208func buildingBootImage(partitionVars android.PartitionVariables) bool {
209	if partitionVars.BoardUsesRecoveryAsBoot {
210		return false
211	}
212
213	if partitionVars.ProductBuildBootImage {
214		return true
215	}
216
217	if len(partitionVars.BoardPrebuiltBootimage) > 0 {
218		return false
219	}
220
221	if len(partitionVars.BoardBootimagePartitionSize) > 0 {
222		return true
223	}
224
225	// TODO: return true if BOARD_KERNEL_BINARIES is set and has a *_BOOTIMAGE_PARTITION_SIZE
226	// variable. However, I don't think BOARD_KERNEL_BINARIES is ever set in practice.
227
228	return false
229}
230
231// Returns the equivalent of the BUILDING_VENDOR_BOOT_IMAGE variable in make. Derived from this logic:
232// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=518;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
233func buildingVendorBootImage(partitionVars android.PartitionVariables) bool {
234	if v, exists := boardBootHeaderVersion(partitionVars); exists && v >= 3 {
235		x := partitionVars.ProductBuildVendorBootImage
236		if x == "" || x == "true" {
237			return true
238		}
239	}
240
241	return false
242}
243
244// Derived from: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/board_config.mk;l=480;drc=5b55f926830963c02ab1d2d91e46442f04ba3af0
245func buildingInitBootImage(partitionVars android.PartitionVariables) bool {
246	if !partitionVars.ProductBuildInitBootImage {
247		if partitionVars.BoardUsesRecoveryAsBoot || len(partitionVars.BoardPrebuiltInitBootimage) > 0 {
248			return false
249		} else if len(partitionVars.BoardInitBootimagePartitionSize) > 0 {
250			return true
251		}
252	} else {
253		if partitionVars.BoardUsesRecoveryAsBoot {
254			panic("PRODUCT_BUILD_INIT_BOOT_IMAGE is true, but so is BOARD_USES_RECOVERY_AS_BOOT. Use only one option.")
255		}
256		return true
257	}
258	return false
259}
260
261func boardBootHeaderVersion(partitionVars android.PartitionVariables) (int, bool) {
262	if len(partitionVars.BoardBootHeaderVersion) == 0 {
263		return 0, false
264	}
265	v, err := strconv.ParseInt(partitionVars.BoardBootHeaderVersion, 10, 32)
266	if err != nil {
267		panic(fmt.Sprintf("BOARD_BOOT_HEADER_VERSION must be an int, got: %q", partitionVars.BoardBootHeaderVersion))
268	}
269	return int(v), true
270}
271
272type dtbImg struct {
273	// whether to include the dtb image in boot image
274	include bool
275
276	// name of the generated dtb image filegroup name
277	name string
278
279	// type of the boot image that the dtb image argument should be specified
280	imgType string
281}
282
283func createDtbImgFilegroup(ctx android.LoadHookContext) dtbImg {
284	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
285	if !partitionVars.BoardIncludeDtbInBootimg {
286		return dtbImg{include: false}
287	}
288	for _, copyFilePair := range partitionVars.ProductCopyFiles {
289		srcDestList := strings.Split(copyFilePair, ":")
290		if len(srcDestList) < 2 {
291			ctx.ModuleErrorf("PRODUCT_COPY_FILES must follow the format \"src:dest\", got: %s", copyFilePair)
292		}
293		if srcDestList[1] == "dtb.img" {
294			moduleName := generatedModuleName(ctx.Config(), "dtb_img_filegroup")
295			ctx.CreateModuleInDirectory(
296				android.FileGroupFactory,
297				filepath.Dir(srcDestList[0]),
298				&struct {
299					Name *string
300					Srcs []string
301				}{
302					Name: proptools.StringPtr(moduleName),
303					Srcs: []string{filepath.Base(srcDestList[1])},
304				},
305			)
306			imgType := "vendor_boot"
307			if !buildingVendorBootImage(partitionVars) {
308				imgType = "boot"
309			}
310			return dtbImg{include: true, name: moduleName, imgType: imgType}
311		}
312	}
313	return dtbImg{include: false}
314}
315
316func createVendorBootConfigImg(ctx android.LoadHookContext) (string, bool) {
317	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
318	bootconfig := partitionVars.InternalBootconfig
319	bootconfigFile := partitionVars.InternalBootconfigFile
320	if len(bootconfig) == 0 && len(bootconfigFile) == 0 {
321		return "", false
322	}
323
324	vendorBootconfigImgModuleName := generatedModuleName(ctx.Config(), "vendor_bootconfig_image")
325
326	ctx.CreateModule(
327		filesystem.BootconfigModuleFactory,
328		&struct {
329			Name             *string
330			Boot_config      []string
331			Boot_config_file *string
332		}{
333			Name:             proptools.StringPtr(vendorBootconfigImgModuleName),
334			Boot_config:      bootconfig,
335			Boot_config_file: proptools.StringPtr(bootconfigFile),
336		},
337	)
338
339	return vendorBootconfigImgModuleName, true
340}
341