11
11
12
12
from klpbuild .klplib .bugzilla import get_bug_title
13
13
from klpbuild .klplib .codestreams_data import get_codestreams_data
14
- from klpbuild .klplib .utils import ARCHS , fix_mod_string , get_mail , get_workdir , get_lp_number
14
+ from klpbuild .klplib .utils import ARCHS , fix_mod_string , get_mail , get_workdir , get_lp_number , get_fname
15
+
16
+
17
+ MACRO_PROTO_SYMS = """\
18
+ <%
19
+ def get_protos(proto_syms):
20
+ proto_list = []
21
+
22
+ if not proto_syms:
23
+ return ''
24
+
25
+ for fname, data in proto_syms.items():
26
+ proto_list.append(f"int {fname}_init(void);")
27
+ if data["cleanup"]:
28
+ proto_list.append(f"void {fname}_cleanup(void);\\ n")
29
+ else:
30
+ proto_list.append(f"static inline void {fname}_cleanup(void);\\ n")
31
+
32
+ return '\\ n' + '\\ n'.join(proto_list)
33
+ %>\
34
+ """
15
35
16
36
17
37
TEMPL_NO_SYMS_H = """\
38
58
% else:
39
59
static inline void ${ fname }_cleanup(void) {}
40
60
% endif %
41
-
61
+ ${get_protos(proto_syms)}
42
62
#else /* !IS_ENABLED(${ config }) */
43
63
44
64
static inline int ${ fname }_init(void) { return 0; }
53
73
% else:
54
74
static inline void ${ fname }_cleanup(void) {}
55
75
% endif
56
-
76
+ ${get_protos(proto_syms)}
57
77
% endif
58
78
#endif /* _${ fname.upper() }_H */
59
79
"""
@@ -432,107 +452,109 @@ def __generate_patched_conf(self, cs):
432
452
433
453
def __generate_header_file (self , lp_path , cs ):
434
454
out_name = f"livepatch_{ self .lp_name } .h"
435
-
436
- lp_inc_dir = Path ()
437
- configs = set ()
438
- config = ""
439
- mod = ""
440
- has_ext = False
441
- has_cleanup = False
442
-
443
- for f , data in cs .files .items ():
444
- configs .add (data ["conf" ])
445
- # If we have external symbols we need an init function to load them. If the module
446
- # isn't vmlinux then we also need an _exit function
447
- if data ["ext_symbols" ]:
448
- has_ext = True
449
-
450
- if data ["module" ] != "vmlinux" :
451
- has_cleanup = True
452
-
453
- # Only populate the config check in the header if the livepatch is
454
- # patching code under only one config. Otherwise let the developer to
455
- # fill it.
456
- if len (configs ) == 1 :
457
- config = configs .pop ()
458
-
459
455
render_vars = {
460
- "fname" : str (Path (out_name ).with_suffix ("" )).replace ("-" , "_" ),
461
- "check_enabled" : self .check_enabled ,
462
- "config" : config ,
463
- "has_cleanup" : has_cleanup ,
456
+ "fname" : get_fname (out_name ),
464
457
}
465
458
466
- header_templ = TEMPL_H
467
- # If we don't have any external symbols then we don't need the empty _init/_exit functions
468
- if cs .needs_ibt or not has_ext :
469
- header_templ = TEMPL_NO_SYMS_H
459
+ # We don't need any setups on IBT besides the livepatch_init/cleanup ones
460
+ header_templ = TEMPL_NO_SYMS_H
461
+
462
+ if not cs .needs_ibt :
463
+ configs = set ()
464
+ config = ""
465
+ has_cleanup = False
466
+ proto_syms = {}
467
+
468
+ for src_file , data in cs .files .items ():
469
+ configs .add (data ["conf" ])
470
+ # If we have external symbols we need an init function to load them. If the module
471
+ # isn't vmlinux then we also need an _exit function
472
+ if data ["ext_symbols" ]:
473
+ if data ["module" ] != "vmlinux" :
474
+ # Used by the livepatch_cleanup
475
+ has_cleanup = True
476
+
477
+ proto_fname = get_fname (cs .lp_out_file (self .lp_name , src_file ))
478
+ proto_syms [proto_fname ] = {"cleanup" : data ["module" ] != "vmlinux" }
479
+
480
+ # If we don't have any external symbols then we don't need the empty _init/_exit functions
481
+ if proto_syms .keys ():
482
+ # Only populate the config check in the header if the livepatch is
483
+ # patching code under only one config. Otherwise let the developer to
484
+ # fill it.
485
+ if len (configs ) == 1 :
486
+ config = configs .pop ()
487
+
488
+ # We there was only one entry in the proto_syms means that we have only one file in
489
+ # in this livepatch, so we are already covered
490
+ # Situations where we don't need any extra symbol prototypes:
491
+ # * we don't have any externalized symbols
492
+ # * the livepatch has only one file (_init/_cleanup for livepatch_ are created by default)
493
+ if len (proto_syms .keys ()) == 1 and len (cs .files .keys ()) == 1 :
494
+ proto_syms = {}
495
+
496
+ render_vars .update ({
497
+ "check_enabled" : self .check_enabled ,
498
+ "config" : config ,
499
+ "has_cleanup" : has_cleanup ,
500
+ "proto_syms" : proto_syms ,
501
+ })
502
+
503
+ header_templ = MACRO_PROTO_SYMS + TEMPL_H
470
504
471
505
with open (Path (lp_path , out_name ), "w" ) as f :
472
- lpdir = TemplateLookup (directories = [lp_inc_dir ], preprocessor = TemplateGen .preproc_slashes )
506
+ lpdir = TemplateLookup (directories = [Path () ], preprocessor = TemplateGen .preproc_slashes )
473
507
f .write (Template (header_templ , lookup = lpdir ).render (** render_vars ))
474
508
475
- def __generate_lp_file (self , lp_path , cs , src_file , use_src_name = False ):
476
- if src_file :
477
- lp_inc_dir = str (cs .get_ccp_work_dir (self .lp_name , src_file ))
478
- lp_file = cs .lp_out_file (self .lp_name , src_file )
479
- fdata = cs .files [str (src_file )]
480
- else :
481
- lp_inc_dir = Path ("non-existent" )
482
- lp_file = None
483
- fdata = {}
484
-
485
- # if use_src_name is True, the final file will be:
486
- # bscXXXXXXX_{src_name}.c
487
- # else:
488
- # livepatch_bscXXXXXXXX.c
489
- if use_src_name :
490
- out_name = lp_file
491
- else :
492
- out_name = f"livepatch_{ self .lp_name } .c"
493
-
494
- user , email = get_mail ()
509
+ def __generate_lp_file (self , lp_path , cs , src_file , out_name ):
495
510
cve = get_codestreams_data ('cve' )
496
511
if not cve :
497
512
cve = "XXXX-XXXX"
498
- cmts = get_codestreams_data ( 'commits' )
513
+ user , email = get_mail ( )
499
514
tvars = {
500
- "include_header" : "livepatch_" in out_name ,
515
+ "check_enabled" : self .check_enabled ,
516
+ "commits" : get_codestreams_data ('commits' ),
517
+ "config" : "CONFIG_CHANGE_ME" ,
501
518
"cve" : cve ,
519
+ "email" : email ,
520
+ "fname" : get_fname (out_name ),
521
+ "include_header" : "livepatch_" in out_name ,
502
522
"lp_name" : self .lp_name ,
503
523
"lp_num" : get_lp_number (self .lp_name ),
504
- "fname" : str (Path (out_name ).with_suffix ("" )).replace ("-" , "_" ),
505
- "year" : datetime .today ().year ,
506
524
"user" : user ,
507
- "email" : email ,
508
- "config" : fdata .get ("conf" , "" ),
509
- "mod" : fix_mod_string (fdata .get ("module" , "" )),
510
- "mod_mutex" : cs .is_mod_mutex (),
511
- "check_enabled" : self .check_enabled ,
512
- "ext_vars" : fdata .get ("ext_symbols" , "" ),
513
- "inc_src_file" : lp_file ,
514
- "ibt" : fdata .get ("ibt" , False ),
515
- "commits" : cmts
525
+ "year" : datetime .today ().year ,
516
526
}
517
527
518
- with open (Path (lp_path , out_name ), "w" ) as f :
519
- lpdir = TemplateLookup (directories = [lp_inc_dir ], preprocessor = TemplateGen .preproc_slashes )
520
-
521
- # If we have multiple source files for the same livepatch,
522
- # create one hollow file to wire-up the multiple _init and
523
- # _clean functions
524
- #
525
- # If we are patching a module, we should have the
526
- # module_notifier armed to signal whenever the module comes on
527
- # in order to do the symbol lookups. Otherwise only _init is
528
- # needed, and only if there are externalized symbols being used.
529
- if not lp_file :
530
- temp_str = TEMPL_HOLLOW
531
- elif tvars ["mod" ]:
528
+ # If we have multiple source files for the same livepatch,
529
+ # create one hollow file to wire-up the multiple _init and
530
+ # _clean functions
531
+ #
532
+ # If we are patching a module, we should have the
533
+ # module_notifier armed to signal whenever the module comes on
534
+ # in order to do the symbol lookups. Otherwise only _init is
535
+ # needed, and only if there are externalized symbols being used.
536
+ if not src_file :
537
+ temp_str = TEMPL_HOLLOW
538
+ lp_inc_dir = Path ("non-existent" )
539
+ else :
540
+ fdata = cs .files [str (src_file )]
541
+ tvars .update ({
542
+ "config" : fdata .get ("conf" , "" ),
543
+ "ext_vars" : fdata .get ("ext_symbols" , "" ),
544
+ "ibt" : fdata .get ("ibt" , False ),
545
+ "inc_src_file" : cs .lp_out_file (self .lp_name , src_file ),
546
+ "mod" : fix_mod_string (fdata .get ("module" , "" )),
547
+ "mod_mutex" : cs .is_mod_mutex (),
548
+ })
549
+
550
+ if tvars ["mod" ]:
532
551
temp_str = TEMPL_GET_EXTS + TEMPL_PATCH_MODULE
533
552
else :
534
553
temp_str = TEMPL_GET_EXTS + TEMPL_PATCH_VMLINUX
554
+ lp_inc_dir = cs .get_ccp_work_dir (self .lp_name , src_file )
535
555
556
+ lpdir = TemplateLookup (directories = [lp_inc_dir ], preprocessor = TemplateGen .preproc_slashes )
557
+ with open (Path (lp_path , out_name ), "w" ) as f :
536
558
f .write (Template (TEMPL_SUSE_HEADER + temp_str , lookup = lpdir ).render (** tvars ))
537
559
538
560
def generate_livepatches (self , cs ):
@@ -549,22 +571,30 @@ def generate_livepatches(self, cs):
549
571
# config entries empty
550
572
self .__generate_header_file (lp_path , cs )
551
573
552
- # Run the template engine for each touched source file.
574
+ # Run the template engine for each generated source file.
553
575
for src_file , _ in files .items ():
554
- self .__generate_lp_file (lp_path , cs , src_file , is_multi_files )
576
+ # if use_src_name is True, the final file will be:
577
+ # bscXXXXXXX_{src_name}.c
578
+ # else:
579
+ # livepatch_bscXXXXXXXX.c
580
+ out_name = f"livepatch_{ self .lp_name } .c" if not is_multi_files else \
581
+ cs .lp_out_file (self .lp_name , src_file )
582
+
583
+ self .__generate_lp_file (lp_path , cs , src_file , out_name )
555
584
556
585
# One additional file to encapsulate the _init and _clenaup methods
557
586
# of the other source files
558
587
if is_multi_files :
559
- self .__generate_lp_file (lp_path , cs , None , False )
588
+ self .__generate_lp_file (lp_path , cs , None , f"livepatch_{ self .lp_name } .c" )
589
+
590
+ create_kbuild (self .lp_name , cs )
560
591
561
- self .__create_kbuild (cs )
562
592
593
+ def create_kbuild (lp_name , cs ):
563
594
# Create Kbuild.inc file adding an entry for all generated livepatch files.
564
- def __create_kbuild (self , cs ):
565
- render_vars = {"bsc" : self .lp_name , "cs" : cs , "lpdir" : cs .get_lp_dir (self .lp_name )}
566
- with open (Path (cs .get_lp_dir (self .lp_name ), "Kbuild.inc" ), "w" ) as f :
567
- f .write (Template (TEMPL_KBUILD ).render (** render_vars ))
595
+ render_vars = {"bsc" : lp_name , "cs" : cs , "lpdir" : cs .get_lp_dir (lp_name )}
596
+ with open (Path (cs .get_lp_dir (lp_name ), "Kbuild.inc" ), "w" ) as f :
597
+ f .write (Template (TEMPL_KBUILD ).render (** render_vars ))
568
598
569
599
570
600
def generate_commit_msg_file (lp_name ):
0 commit comments