-
Notifications
You must be signed in to change notification settings - Fork 0
/
adjust_9_0-systemd.py
596 lines (512 loc) · 21.6 KB
/
adjust_9_0-systemd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
# adjust_9.0-systemd.py - adjusting for a specific version of the book
"""Configuration data to adjust the build process for version 9.0-systemd.
This file defines two data structures:
- directives: new or modified snippets to adjust the build instructions
- param_mapping: what variables should replace the placeholders in snippets ?
The variables themselves (with the actual values you want to use) are defined
in a third structure called 'variables', in the config.py file.
Collectively, these data structures define the behaviour of the software.
Directives and param_mapping are used to adapt the build to a specific version
of the book, and variables customizes the build for a given environment.
"""
#-------------------------------------------------------------------------------
# directives
#-------------------------------------------------------------------------------
# Directives are commands to change the behaviour from that which is prescribed
# by the LFS book. This is mostly done to adapt commands that were meant for
# interactive use to the new situation where everything is being done in a
# batch script, but it can also be done simply to adapt the build process to
# your personal tastes and preferences.
# FIXME once you start testing with different versions, you see what a bad idea
# it is to organize the sections based on their id, because this can change
# from one version to another (adding just one new package changes the id of
# all the subsequent packages).
# The 'directives' dictionary uses section ids as keys. The value associated to
# a key may be:
# - a simple string, which is a command such as 'ignore' (curr.the only one)
# - an array of tuples, each tuple describes a directive
# A directive tuple has the form
# - target id
# - command
# - argument (optional)
# The target id is either the id of a snippet to which the directive will be
# applied, or it's just a number used to ensure the correct ordering of
# directives. The tuples in a section value should always be ordered by target
# id.
# Commands may be:
# - ignore: just skip the section or snippet
# - replace: like the name says, whatever snippet (userinput or screen) was
# parsed from the book gets replaced with the snippet from this directive
# (argument). The new snippet may include <code> elements which will be
# replaced, *if* you don't forget to add them to param_mapping.
# - push: from this point on, script code being generated must be re-directed
# to a new file, named in the directive (and normally used on the previous
# command). The code and filename get pushed onto a stack. The argument is the
# filename.
# - pop: pop code from stack, write it to file
# - add: add a new snippet. Be sure to use a non-integer target id, as integer
# target id's come from parsing the book, and the code may make some assumtions
# about that.
directives = {
# Help
'1.05': 'ignore',
# Host System Requirements
'2.02': [
# Add an automated check on the system requirements. We check that sh
# is a symbolic link to bash, and that no required command is
# missing. We don't check for mismatched versions.
# Snippet 2.02_0 already runs "bash version-check.sh", but if I did a
# 'replace', I'd have to include the entire script here, and that
# wouldn't help readability.
(0.5, 'add', """# Note the "|&" to pipe stdout and stderr together
bash version-check.sh |& grep -E \\
"(ERROR: /bin/sh does not point to bash|: command not found)" &> /dev/null
err=$?
if [ $err -eq 1 ]; then
# grep exit code is 1 if no lines were selected
echo Check: 2.02: no errors detected.
else
echo Check: 2.02: host system requirements FAILED, exiting.
exit
fi
rm -f version-check.sh"""
),
],
# Creating a File System on the Partition
'2.05': [
(1, 'ignore'), # I already have a swap partition
],
# Mounting the New Partition
'2.07': [
# Snippet #0 did the mount, so from this point on, $LFS is accessible
# Attempting to copy the kernel config file will fail the first time
# around, this is expected and can be safely ignored.
(0.5, 'add', """mkdir $LFS/pkg_lfs
cp /var/tmp/lfs/<code>lfs_version</code>/script_0?.sh $LFS/pkg_lfs
cp /var/tmp/lfs/<code>lfs_version</code>/6.*_expected.txt $LFS/pkg_lfs
cp /var/tmp/lfs/<code>lfs_version</code>/6.*_script.sh $LFS/pkg_lfs
cp /var/tmp/lfs/<code>lfs_version</code>/config.<code>kernel_version</code> $LFS/pkg_lfs"""
),
# Use this if you have multiple partitions for LFS, we don't.
(1, 'ignore'),
# LFS partition will be remounted when we run the scripts again
(2, 'ignore'),
# We're not creating a swap partition
(3, 'ignore'),
],
# Introduction
'3.01': [
# Packages are downloaded the first time the parsing script runs, so
# here we just need to copy them from LFS_DATA to $LFS/sources.
(2, 'replace', 'cp <code>pkg_repository</code>/*.* $LFS/sources'),
# Checksums have been checked after download, see pkg.py:get_all().
(3, 'ignore'),
],
# Adding the LFS User
'4.03': [
# We never login with user 'lfs', so it doesn't need a password
(1, 'ignore'),
# All the shell script code that needs to be run as user 'lfs' will be
# generated by the python code and written into the script_01.sh file,
# which we execute at this point.
(4, 'replace', 'su - lfs /var/tmp/lfs/<code>lfs_version</code>/script_01.sh'),
# This snippet is used internally by the python code to indicate "start
# accumulating into a new file" and "push a new script on the script
# stack"
(4.5, 'push', '/var/tmp/lfs/<code>lfs_version</code>/script_01.sh'),
],
# This is a tricky part, for two reasons. First, snippet #0 just puts an
# 'exec' command into ~/.bash_profile file, it doesn't run it. Then snippet
# #2 sources the file, and that's when the 'exec' gets executed. Second,
# executing the 'su' command with a script makes the shell non-interactive,
# hence it will not read .bashrc. This is solved by snippet #2.6.
# Setting Up the Environment
'4.04': [
# Note the r-string here, otherwise \u gets interpreted as unicode escape
(0, 'replace', r"""cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' \
/bin/bash /var/tmp/lfs/<code>lfs_version</code>/script_02.sh
EOF"""
),
# 4.04 #1 will be run normally, we're still inside script_01.sh. We
# replace just to put a placeholder, to avoid hardcoding /mnt/lfs.
(1, 'replace', """cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=<code>lfs_mount_point</code>
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/tools/bin:/bin:/usr/bin
export LFS LC_ALL LFS_TGT PATH
EOF"""
),
# 4.04 #2 runs 'source ~/.bash_profile', which runs 'exec', thereby
# starting a new shell running the script file script_02.
(2.5, 'push', '/var/tmp/lfs/<code>lfs_version</code>/script_02.sh'),
# This snippet inserts code at the very beginning of script_02.sh. We
# do this because 'su' runs a non-interactive shell which does not read
# /.bashrc, and we need it to be sourced (it defines LFS).
(2.6, 'add', 'source ~/.bashrc')
],
# About SBUs
'4.05': 'ignore', # But maybe set MAKEFLAGS="-j 8" elsewhere?
# Toolchain Technical Notes
'5.02': 'ignore',
# Package building sections
'5.07': [(2, 'ignore')], # harmless warning
'5.11': [(2, 'ignore')], # tests are optional in chapter 5
'5.12': [(3, 'ignore')], # tests are optional in chapter 5
'5.13': [(2, 'ignore')], # tests are optional in chapter 5
'5.14': [(3, 'ignore')], # tests are optional in chapter 5
'5.16': [(2, 'ignore')], # tests are optional in chapter 5
'5.17': [(2, 'ignore')], # tests are optional in chapter 5
'5.19': [(2, 'ignore')], # tests are optional in chapter 5
'5.20': [(2, 'ignore')], # tests are optional in chapter 5
'5.21': [(2, 'ignore')], # tests are optional in chapter 5
'5.22': [(3, 'ignore')], # tests are optional in chapter 5
'5.23': [(2, 'ignore')], # tests are optional in chapter 5
'5.25': [(2, 'ignore')], # tests are optional in chapter 5
'5.26': [(2, 'ignore')], # tests are optional in chapter 5
'5.27': [(3, 'ignore')], # tests are optional in chapter 5
'5.28': [(2, 'ignore')], # tests are optional in chapter 5
'5.31': [(2, 'ignore')], # tests are optional in chapter 5
'5.32': [(2, 'ignore')], # tests are optional in chapter 5
'5.33': [(2, 'ignore')], # tests are optional in chapter 5
'5.35': [(2, 'ignore')], # tests are optional in chapter 5
# Normally I would've ignored the entire "Stripping" section, but I need a
# place to add the 2.7 snippet after all the sections in chapter 5 have
# been done (and their sbus calculated). FIXME add a mechanism to add a
# section.
# Stripping
'5.36': [
(0, 'ignore'),
(1, 'ignore'),
(2, 'ignore'),
(2.5, 'pop'), # end of script_02.sh, pushed in 4.04_2.5
(2.6, 'pop'), # end of script_01.sh, pushed in 4.03_4.5
# Back to the 'root' user, sending script code to script_00.sh
(2.7, 'add', """cp /var/tmp/lfs/<code>lfs_version</code>/sbu_in_secs.txt $LFS/pkg_lfs
cp /var/tmp/lfs/<code>lfs_version</code>/sbu_total.txt $LFS/pkg_lfs"""
),
],
# Package Management
'6.03': 'ignore',
# Entering the Chroot Environment
'6.04': [
# Note the r-string here, otherwise \u gets interpreted as unicode escape
(0, 'replace', r"""chroot "$LFS" /tools/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin \
/tools/bin/bash --login +h /pkg_lfs/script_03.sh"""
),
(0.5, 'push', '/var/tmp/lfs/<code>lfs_version</code>/script_03.sh'),
],
# Creating Essential Files and Symlinks
'6.06': [(4, 'ignore')], # don't care about the prompt
# Glibc-2.30
'6.09': [
(14, 'ignore'), # this is an alternative
(17, 'ignore'), # we set the time zone in one of our variables
],
# Binutils-2.32
'6.16': [(2, 'ignore')], # alternate error message
# GMP-6.1.2
'6.17': [
(0, 'ignore'), # not building for 32-bit x86
(1, 'ignore'), # optimize for host processor
],
# Shadow-4.7
'6.20': [
(2, 'ignore'), # don't build with Cracklib support
(8, 'ignore'), # don't enable shadowed passwords
(9, 'ignore'), # don't enable shadowed group passwords
(10, 'ignore'), # let useradd create a mailbox
# Here you have the root password 'abcdef01' in the clear, this is done
# so that the entire build script can be run unattended. Don't forget
# to change it later, if securing access to the LFS system is
# important.
(11, 'replace', 'echo root:abcdef01 | chpasswd'), # passwd root
],
# GCC-9.2.0
'6.21': [(20, 'ignore')], # 32-bit version of the previous result
# Ncurses-6.1
'6.24': [(9, 'ignore')], # don't create non-wide-character libraries
# Bash-5.0
'6.34': [
(5, 'replace', 'exec /bin/bash --login +h /pkg_lfs/script_04.sh'),
(5.5, 'push', '/var/tmp/lfs/<code>lfs_version</code>/script_04.sh'),
],
# Texinfo-6.6
'6.70': [(5, 'ignore')], # only if the dir file needs to be recreated
# Vim-8.1.1846
'6.71': [
(9, 'ignore'), # vim -c ':options'
(10, 'ignore'), # spell files
],
# Util-linux-2.34
'6.75': [(4, 'ignore')], # Running the test suite as root can be harmful
# Stripping Again
'6.78': 'ignore', # snippet #1 does an 'exec', need more study here
# Cleaning Up
'6.79': [
# Snippet #0 must still be run in the current chroot environment
(0.5, 'pop'), # end of script_04.sh, pushed in 6.34_5.5
(0.6, 'pop'), # end of script_03.sh, pushed in 6.04_0.5
# Back to script_00.sh
# Note the r-string here, otherwise \u gets interpreted as unicode escape
(1, 'replace', r"""chroot "$LFS" /usr/bin/env -i \
HOME=/root \
TERM="$TERM" \
PS1='(lfs chroot) \u:\w\$ ' \
PATH=/bin:/usr/bin:/sbin:/usr/sbin \
/bin/bash --login /pkg_lfs/script_05.sh"""
),
(1.5, 'push', '/var/tmp/lfs/<code>lfs_version</code>/script_05.sh'),
# Snippets #2 and #3 will be generated into script_05.sh
],
# General Network Configuration
'7.02': [
(0, 'ignore'), # we don't want classic or customized
(1, 'ignore'), # we don't want classic or customized
(2, 'ignore'), # we don't want static IP
# snippet #3 DHCP is what we want
(4, 'ignore'), # we don't use systemd-resolved
# snippet #5 static resolv.conf configuration is what we want
(7, 'ignore'), # these are just examples
(8, 'ignore'), # these are just examples
(10, 'ignore'), # we're not using a static address
],
# Overview of Device and Module Handling
'7.03': 'ignore',
# Managing Devices
'7.04': 'ignore',
# Configuring the system clock
'7.05': 'ignore',
# Configuring the Linux Console
'7.06': [
# Set your own keyboard layout here
(0, 'replace', """cat > /etc/vconsole.conf << "EOF"
KEYMAP=<code>fr</code>
EOF"""
),
(1, 'ignore'), # example commands
(2, 'ignore'), # example commands
],
# Configuring the System Locale
'7.07': [
(0, 'ignore'), # example commands
(1, 'ignore'), # example commands
(2, 'ignore'), # example output
(3, 'ignore'), # example commands
(4, 'ignore'), # example output
(5, 'ignore'), # example output
# snippet #6 is all we need, to create the /etc/locale.conf file
(7, 'ignore'), # example commands
(8, 'ignore'), # example commands
],
# Systemd Usage and Configuration
'7.10': [
# Run #0, don't clear the screen at the end of the boot sequence
(1, 'ignore'), # optional
(2, 'ignore'), # example syntax
(3, 'ignore'), # optional example
(4, 'ignore'), # optional example
],
# Creating the /etc/fstab File
'8.02': [
# Not using swap
(0, 'replace', """cat > /etc/fstab << "EOF"
# file system mount-point type options dump fsck
# order
/dev/<code>xxx</code> / <code>fff</code> defaults 1 1
# End /etc/fstab
EOF"""
),
(1, 'ignore'), # optional
(2, 'ignore'), # optional
(3, 'ignore'), # optional
],
# Linux-5.2.8
'8.03': [
(1, 'ignore'), # example kernel configurations
(2, 'ignore'), # UEFI support option
# Once a kernel has been built, snippets 8.03_3.5 (below) and 9.03_0.6
# in that build run have saved the kernel config file outside of the
# chrooted environment. In the next run, snippet 2.07_0.5 copies the
# config file back to $LFS (or / inside the chroot'ed environment) and
# here we copy it back into the source directory.
(2.5, 'add', 'cp /pkg_lfs/config.<code>kernel_version</code> .config'),
########################################################################
# Snippet #3 is the 'make menuconfig' step. It needs to be run the
# first time, to produce a .config file, so initially we do not ignore
# the snippet (keep it commented out).
#
# Uncomment the next line after a first kernel has been built, and a
# config file has been saved to /var/tmp/lfs/{version}, that file will
# be reused.
# (3, 'ignore'),
########################################################################
# After running 'make menuconfig' once manually, a config file was
# created in /sources/linux-5.28 (inside the chroot'ed environment).
# Here we save it to /pkg_lfs (i.e. $LFS outside the chroot) before the
# source directory gets removed).
(3.5, 'add', 'cp .config /pkg_lfs/config.<code>kernel_version</code>'),
(6, 'ignore'), # we don't have a separate boot partition
],
# We're not going to install grub on the target LFS system, we assume we're
# building on a host Linux system that has grub installed, and we simply
# add a menuentry for the new LFS system.
# Normally I would keep this section, ignore most existing snippets, and
# replace one of them with a new snippet to append some code to
# grub.cfg. However, section 8.04 runs inside the chroot'ed environment
# where the hosts's grub.cfg is not accessible, so this needs to be
# postponed to section 9.03.
# Using GRUB to Set Up the Boot Process
'8.04': 'ignore',
# The End
'9.01': [
(0, 'replace', """cat > /etc/os-release << "EOF"
NAME="Linux From Scratch"
VERSION="<code>lfs_version</code>"
ID=lfs
PRETTY_NAME="Linux From Scratch <code>lfs_version</code>"
VERSION_CODENAME="<code>builder_name</code>"
EOF"""
),
(1, 'replace', 'echo <code>lfs_version</code> > /etc/lfs-release'),
(2, 'replace', """cat > /etc/lsb-release << "EOF"
DISTRIB_ID="Linux From Scratch"
DISTRIB_RELEASE="<code>lfs_version</code>"
DISTRIB_CODENAME="<code>builder_name</code>"
DISTRIB_DESCRIPTION="Linux From Scratch"
EOF"""
),
],
# Rebooting the System
'9.03': [
(0, 'ignore'), # the next 'pop' logs us out
(0.5, 'pop'), # end of script_05.sh, pushed in 6.79_1.5
# Back to the 'root' user, and out of the chroot'ed
# environment. All script code will now go to script_00.sh.
# Save the kernel config file from $LFS/pkg_lfs to /var/tmp
(0.6, 'add', ('cp $LFS/pkg_lfs/config.<code>kernel_version</code>'
+ ' /var/tmp/lfs/<code>lfs_version</code>')),
# Add a new LFS entry to the host's grub.cfg file, checking that it's
# not already there
(0.7, 'add', """# Add a new menuentry to grub.cfg, but only if it's not there already
# Create a file with the new menuentry we need in grub.cfg
temp1=$(mktemp new_menuentry.XXXXXX)
cat > $temp1 <<EOF
# Manually added for LFS
menuentry "GNU/Linux, Linux <code>kernel_version</code>-lfs-<code>lfs_version</code>" {
insmod ext2
set root=(hd0,<code>linux_part_nbr</code>)
linux /boot/vmlinuz-<code>kernel_version</code>-lfs-<code>lfs_version</code> root=/dev/<code>linux_partition</code> ro
}
EOF
nbr_lines=$(wc $temp1 | awk '{print $1}')
# Get the tail of grub.cfg for the same number of lines
temp2=$(mktemp grub_tail.XXXXXX)
tail -$nbr_lines <code>grub_cfg_path</code>/grub.cfg > $temp2
# If the files are identical, the menuentry we want is already present
diff $temp1 $temp2 > /dev/null
err=$?
if [ $err -eq 1 ]; then
# Files differ, the new menuentry isn't there yet, I can append it
cat $temp1 >> <code>grub_cfg_path</code>/grub.cfg
fi
rm -f $temp1 $temp2"""
),
(3, 'ignore'), # we don't have multiple partitions
(4, 'ignore'), # don't reboot automatically
],
# You may now write script_00.sh to file
}
#-------------------------------------------------------------------------------
# Mapping variables or values to parameters
#-------------------------------------------------------------------------------
# If you add entries to 'directives', either 'add' or 'replace', that contain
# placeholders, then you must also add them here for replacement to occur.
param_mapping = {
# section, snippet, args
'2.05': [
(0, ['linux_partition']),
(1, ['swap_partition']),
],
'2.06': [
(0, ['lfs_mount_point']),
],
'2.07': [
(0, ['linux_partition']),
(0.5, ['lfs_version', 'lfs_version', 'lfs_version', 'lfs_version', 'kernel_version']),
(1, ['linux_partition', '']),
(2, ['linux_partition', 'lfs_mount_point', 'fs_type']),
(3, ['swap_partition']),
],
'3.01': [
(2, ['pkg_repository']),
],
'4.03': [
(4, ['lfs_version']),
(4.5, ['lfs_version']),
],
'4.04': [
(0, ['lfs_version']),
(1, ['lfs_mount_point']),
(2.5, ['lfs_version']),
],
'5.36': [
(2.7, ['lfs_version', 'lfs_version']),
],
'6.04': [
(0.5, ['lfs_version']),
],
'6.34': [
(5.5, ['lfs_version']),
],
'6.09': [
(18, ['time_zone']),
],
'6.59': [
(0, ['paper_size']),
],
'6.79': [
(1.5, ['lfs_version']),
],
'7.02': [
(2, ['network_device', 'domain_name']),
(5, ['domain_name', 'nameserver1', 'nameserver2']),
(6, ['hostname']),
(9, ['fqdn', 'hostname']),
(10, ['fqdn', 'hostname', 'ip_address', 'fqdn', 'hostname',
'host_aliases']),
],
'7.06': [
(0, ['keymap']),
],
'7.07': [
(6, ['locale_params']),
],
'8.02': [
(0, ['linux_partition', 'fs_type']),
],
'8.03': [
(2.5, ['kernel_version']),
(3.5, ['kernel_version']),
],
'9.01': [
(0, ['lfs_version', 'lfs_version', 'builder_name']),
(1, ['lfs_version']),
(2, ['lfs_version', 'builder_name']),
],
'9.03': [
(0.6, ['kernel_version', 'lfs_version']),
(0.7, ['kernel_version', 'lfs_version', 'linux_part_nbr',
'kernel_version', 'lfs_version', 'linux_partition',
'grub_cfg_path', 'grub_cfg_path']),
],
}
# End of adjust_9.0-systemd.py
#===============================================================================