• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-bootloader / 16930127664

13 Aug 2025 07:06AM UTC coverage: 87.315% (+0.04%) from 87.277%
16930127664

Pull #723

github

schubi2
added testcase
Pull Request #723: Bls nvram

30 of 31 new or added lines in 4 files covered. (96.77%)

5 existing lines in 1 file now uncovered.

3483 of 3989 relevant lines covered (87.32%)

12.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.53
/src/lib/bootloader/systemdboot.rb
1
# frozen_string_literal: true
2

3
require "fileutils"
1✔
4
require "yast"
1✔
5
require "bootloader/sysconfig"
1✔
6
require "bootloader/cpu_mitigations"
1✔
7
require "bootloader/bls"
1✔
8
require "bootloader/bls_sections"
1✔
9
require "cfa/grub2/default"
1✔
10

11
Yast.import "Report"
1✔
12
Yast.import "Arch"
1✔
13
Yast.import "ProductFeatures"
1✔
14
Yast.import "BootStorage"
1✔
15
Yast.import "Stage"
1✔
16

17
module Bootloader
1✔
18
  # Represents systemd bootloader with efi target
19
  class SystemdBoot < BootloaderBase
1✔
20
    include Yast::Logger
1✔
21
    include Yast::I18n
1✔
22

23
    CMDLINE = "/etc/kernel/cmdline"
1✔
24

25
    # @!attribute timeout
26
    #   @return [Integer] menu timeout
27
    attr_accessor :timeout
1✔
28
    alias_method :menu_timeout, :timeout # Agama compatible
1✔
29
    alias_method :menu_timeout=, :timeout= # Agama compatible
1✔
30

31
    # @!attribute secure_boot
32
    #   @return [Boolean] current secure boot setting
33
    attr_accessor :secure_boot
1✔
34

35
    # @!attribute update_nvram
36
    #   @return [Boolean] current update nvram setting
37
    attr_accessor :update_nvram
1✔
38

39
    attr_reader :sections
1✔
40

41
    # @!attribute pmbr_action
42
    #   @return [:remove, :add, :nothing]
43
    attr_accessor :pmbr_action
1✔
44

45
    def initialize
1✔
46
      super
64✔
47

48
      textdomain "bootloader"
64✔
49
      # For kernel parameters we are using the same data structure
50
      # like grub2 in order to be compatible with all calls.
51
      @kernel_container = ::CFA::Grub2::Default.new
64✔
52
      @explicit_cpu_mitigations = false
64✔
53
      @pmbr_action = :nothing
64✔
54
      @sections = ::Bootloader::BlsSections.new
64✔
55
      @update_nvram = true
64✔
56
    end
57

58
    def kernel_params
1✔
59
      @kernel_container.kernel_params
33✔
60
    end
61

62
    # rubocop:disable Metrics/AbcSize
63
    def merge(other)
1✔
64
      log.info "merging: timeout: #{timeout}=>#{other.timeout}"
1✔
65
      log.info "         secure_boot: #{secure_boot}=>#{other.secure_boot}"
1✔
66
      log.info "         update_nvram: #{update_nvram}=>#{other.update_nvram}"
1✔
67
      log.info "         mitigations: #{cpu_mitigations.to_human_string}=>" \
1✔
68
               "#{other.cpu_mitigations.to_human_string}"
69
      log.info "         pmbr_action: #{pmbr_action}=>#{other.pmbr_action}"
1✔
70
      log.info "         kernel_params: #{kernel_params.serialize}=>" \
1✔
71
               "#{other.kernel_params.serialize}"
72
      log.info "         default menu: #{@sections.default}=>" \
1✔
73
               "#{other.sections.default}"
74
      super
1✔
75
      self.timeout = other.timeout unless other.timeout.nil?
1✔
76
      self.secure_boot = other.secure_boot unless other.secure_boot.nil?
1✔
77
      self.pmbr_action = other.pmbr_action if other.pmbr_action
1✔
78
      self.update_nvram = other.update_nvram unless other.update_nvram.nil?
1✔
79

80
      kernel_serialize = kernel_params.serialize
1✔
81
      # handle specially noresume as it should lead to remove all other resume
82
      kernel_serialize.gsub!(/resume=\S+/, "") if other.kernel_params.parameter("noresume")
1✔
83

84
      # prevent double cpu_mitigations params
85
      kernel_serialize.gsub!(/mitigations=\S+/, "") if other.kernel_params.parameter("mitigations")
1✔
86

87
      new_kernel_params = "#{kernel_serialize} #{other.kernel_params.serialize}"
1✔
88
      # deduplicate identicatel parameter. Keep always the last one ( so reverse is needed ).
89
      new_params = new_kernel_params.split.reverse.uniq.reverse.join(" ")
1✔
90

91
      @kernel_container.kernel_params.replace(new_params)
1✔
92

93
      # explicitly set mitigations means overwrite of our
94
      self.cpu_mitigations = other.cpu_mitigations if other.explicit_cpu_mitigations
1✔
95

96
      @sections.default = other.sections.default if other.sections.default
1✔
97

98
      log.info "merging result: timeout: #{timeout}"
1✔
99
      log.info "                secure_boot: #{secure_boot}"
1✔
100
      log.info "                update_nvram: #{update_nvram}"
1✔
101
      log.info "                mitigations: #{cpu_mitigations.to_human_string}"
1✔
102
      log.info "                kernel_params: #{kernel_params.serialize}"
1✔
103
      log.info "                pmbr_action: #{pmbr_action}"
1✔
104
      log.info "                default menu: #{@sections.default}"
1✔
105
    end
106
    # rubocop:enable Metrics/AbcSize
107

108
    def cpu_mitigations
1✔
109
      CpuMitigations.from_kernel_params(kernel_params)
6✔
110
    end
111

112
    def explicit_cpu_mitigations
1✔
113
      @explicit_cpu_mitigations ? cpu_mitigations : nil
1✔
114
    end
115

116
    def cpu_mitigations=(value)
1✔
117
      log.info "set mitigations to #{value.to_human_string}"
×
118
      @explicit_cpu_mitigations = true
×
119
      value.modify_kernel_params(kernel_params)
×
120
    end
121

122
    def read
1✔
123
      super
4✔
124

125
      @sections.read
4✔
126
      self.timeout = Bls.menu_timeout
4✔
127
      self.secure_boot = Systeminfo.secure_boot_active?
4✔
128
      self.update_nvram = Systeminfo.update_nvram_active?
4✔
129

130
      lines = ""
4✔
131
      filename = File.join(Yast::Installation.destdir, CMDLINE)
4✔
132
      if File.exist?(filename)
4✔
133
        File.open(filename).each do |line|
4✔
134
          lines = + line
4✔
135
        end
136
      end
137
      @kernel_container.kernel_params.replace(lines)
4✔
138
    end
139

140
    # Write bootloader settings to disk
141
    def write(etc_only: false)
1✔
142
      super
5✔
143
      log.info("Writing settings...")
5✔
144
      write_kernel_parameter
5✔
145
      if Yast::Stage.initial # while new installation only (currently)
5✔
146
        Bls.install_bootloader
5✔
147
        Bls.set_authentication
5✔
148
      end
149

150
      Bls.create_menu_entries
5✔
151
      Bls.write_menu_timeout(timeout)
5✔
152
      @sections.write
5✔
153
      Pmbr.write_efi(pmbr_action)
5✔
154

155
      true
5✔
156
    end
157

158
    def propose
1✔
159
      super
4✔
160
      log.info("Propose settings...")
4✔
161
      if @kernel_container.kernel_params.empty?
4✔
162
        kernel_line = Yast::BootArch.DefaultKernelParams(Yast::BootStorage.propose_resume)
4✔
163
        @kernel_container.kernel_params.replace(kernel_line)
4✔
164
      end
165
      self.timeout = Yast::ProductFeatures.GetIntegerFeature("globals", "boot_timeout").to_i
4✔
166
      self.secure_boot = Systeminfo.secure_boot_supported?
4✔
167
      # for UEFI always remove PMBR flag on disk (bnc#872054)
168
      self.pmbr_action = :remove
4✔
169
      self.update_nvram = true
4✔
170
    end
171

172
    # Secure boot setting shown in summary screen.
173
    # sdbootutil intialize secure boot if shim has been installed.
174
    #
175
    # @return [String]
176
    def secure_boot_summary
1✔
177
      link = if secure_boot
2✔
178
        "<a href=\"disable_secure_boot\">(#{_("disable")})</a>"
×
179
      else
180
        "<a href=\"enable_secure_boot\">(#{_("enable")})</a>"
2✔
181
      end
182

183
      "#{_("Secure Boot:")} #{status_string(secure_boot)} #{link}"
2✔
184
    end
185

186
    # Update nvram shown in summary screen
187
    #
188
    # @return [String]
189
    def update_nvram_summary
1✔
190
      link = if update_nvram
2✔
191
        "<a href=\"disable_update_nvram\">(#{_("disable")})</a>"
2✔
192
      else
NEW
193
        "<a href=\"enable_update_nvram\">(#{_("enable")})</a>"
×
194
      end
195

196
      "#{_("Update NVRAM:")} #{status_string(update_nvram)} #{link}"
2✔
197
    end
198

199
    # Display bootloader summary
200
    # @return a list of summary lines
201
    def summary(*)
1✔
202
      result = [
203
        Yast::Builtins.sformat(
2✔
204
          _("Boot Loader Type: %1"),
205
          "Systemd Boot"
206
        )
207
      ]
208
      result << secure_boot_summary if Systeminfo.secure_boot_available?(name)
2✔
209
      result << update_nvram_summary if Systeminfo.nvram_available?(name)
2✔
210
      result
2✔
211
    end
212

213
    def name
1✔
214
      "systemd-boot"
15✔
215
    end
216

217
    def packages
1✔
218
      res = super
1✔
219
      res << "sdbootutil" << "systemd-boot"
1✔
220

221
      if ["x86_64", "aarch64"].include?(Yast::Arch.architecture)
1✔
222
        res << "shim"
1✔
223
      else
224
        log.warn "Unknown architecture #{Yast::Arch.architecture} for systemd-boot"
×
225
      end
226

227
      res
1✔
228
    end
229

230
    def delete
1✔
231
      log.warn("is currently not supported")
16✔
232
    end
233

234
    # overwrite BootloaderBase version to save secure boot
235
    def write_sysconfig(prewrite: false)
1✔
236
      sysconfig = Bootloader::Sysconfig.new(bootloader: name,
×
237
        secure_boot: secure_boot, trusted_boot: false,
238
        update_nvram: update_nvram)
239
      prewrite ? sysconfig.pre_write : sysconfig.write
×
240
    end
241

242
  private
1✔
243

244
    def write_kernel_parameter
1✔
245
      # writing kernel parameter to /etc/kernel/cmdline
246
      File.open(File.join(Yast::Installation.destdir, CMDLINE), "w+") do |fw|
5✔
247
        if Yast::Stage.initial # while new installation only
5✔
248
          fw.puts("root=#{Yast::BootStorage.root_partitions.first.name} #{kernel_params.serialize}")
5✔
249
        else # root entry is already available
250
          fw.puts(kernel_params.serialize)
×
251
        end
252
      end
253
    end
254
  end
255
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc