| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Linux::Bootloader::Detect; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Linux::Bootloader::Detect - detects the bootloader and architecture of the system. |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Attempts to determine the bootloader by checking for configuration files |
|
10
|
|
|
|
|
|
|
for grub, lilo, elilo and yaboot then searching the master boot record |
|
11
|
|
|
|
|
|
|
for GRUB, LILO, ELILO and YABOOT. |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Determines the architecture by running uname -m. |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
To attempt to discover the bootloader being used by the system |
|
18
|
|
|
|
|
|
|
detect_bootloader first calls detect_bootloader_from_conf attempts to locate |
|
19
|
|
|
|
|
|
|
/boot/grub/menu.lst, /etc/lilo.conf, /boot/efi/elilo.conf and |
|
20
|
|
|
|
|
|
|
/etc/yaboot.conf and returns the corresponding bootloader name. If |
|
21
|
|
|
|
|
|
|
either undef of multiple are returned because no configuration files or |
|
22
|
|
|
|
|
|
|
multiple configuration files were found detect_bootloader calls |
|
23
|
|
|
|
|
|
|
detect_bootloader_from_mbr which generates a list of all devices accessable from |
|
24
|
|
|
|
|
|
|
the /dev directory reading in the first 512 bytes from each hd and sd |
|
25
|
|
|
|
|
|
|
device using head then redirects the output to grep to determine if |
|
26
|
|
|
|
|
|
|
"GRUB", "LILO", "ELILO" or "YABOOT" is present returning the |
|
27
|
|
|
|
|
|
|
corresponding value if exactly one mbr on the system contained a |
|
28
|
|
|
|
|
|
|
bootloader or multiple if more than one was found and undef if none were |
|
29
|
|
|
|
|
|
|
found. detect_bootloader returns either grub, lilo, elilo, yaboot or |
|
30
|
|
|
|
|
|
|
undef. |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
To attempt to discover the architecture of the system |
|
33
|
|
|
|
|
|
|
detect_architecture makes a uname -m system call returning x86, ppc, |
|
34
|
|
|
|
|
|
|
ia64 or undef. |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head1 FUNCTIONS |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
=cut |
|
39
|
|
|
|
|
|
|
|
|
40
|
3
|
|
|
3
|
|
47716
|
use strict; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
121
|
|
|
41
|
3
|
|
|
3
|
|
18
|
use warnings; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
104
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
3
|
|
|
3
|
|
26
|
use vars qw( $VERSION ); |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
1996
|
|
|
44
|
|
|
|
|
|
|
our $VERSION = '1.2'; |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head3 detect_architecture([style]) |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Input: |
|
49
|
|
|
|
|
|
|
Output: string |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
This function determines the architecture by calling uname -m. By |
|
52
|
|
|
|
|
|
|
default it will report back exactly what uname -m reports, but if you |
|
53
|
|
|
|
|
|
|
specify a "style", detect_architecture will do some mappings. Possible |
|
54
|
|
|
|
|
|
|
styles include: |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Style Example return values (not an exhaustive list...) |
|
57
|
|
|
|
|
|
|
[none] i386, i686, sparc, sun4u, ppc64, s390x, x86_64, parisc64 |
|
58
|
|
|
|
|
|
|
linux i386, i386, sparc, sparc, ppc64, s390, x86_64, parisc |
|
59
|
|
|
|
|
|
|
gentoo x86, x86, sparc, sparc, ppc64, amd64, hppa |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Returns undef on error. |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub detect_architecture { |
|
66
|
4
|
|
100
|
4
|
1
|
59
|
my $arch_style = shift || 'uname'; |
|
67
|
|
|
|
|
|
|
|
|
68
|
4
|
|
|
|
|
10
|
my $arch; |
|
69
|
4
|
100
|
|
|
|
31
|
if ($arch_style eq 'linux') { |
|
|
|
100
|
|
|
|
|
|
|
70
|
1
|
|
|
|
|
9256
|
$arch = `uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/s390x/s390/ -e s/parisc64/parisc/`; |
|
71
|
1
|
|
|
|
|
27
|
chomp $arch; |
|
72
|
|
|
|
|
|
|
} elsif ($arch_style eq 'gentoo') { |
|
73
|
1
|
|
|
|
|
32711
|
$arch = `uname -m | sed -e s/i.86/x86/ -e s/sun4u/sparc/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/x86_64/amd64/ -e s/sparc.*/sparc/ -e s/parisc.*/hppa/`; |
|
74
|
1
|
|
|
|
|
25
|
chomp $arch; |
|
75
|
|
|
|
|
|
|
} else { |
|
76
|
2
|
|
|
|
|
57519
|
$arch = `uname -m`; |
|
77
|
2
|
|
|
|
|
43
|
chomp $arch; |
|
78
|
|
|
|
|
|
|
} |
|
79
|
4
|
|
|
|
|
228
|
return $arch; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head3 detect_bootloader(['device1', 'device2', ...]) |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
Input: devices to detect against (optional) |
|
85
|
|
|
|
|
|
|
Output: string |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This function attempts to determine the bootloader being used on the |
|
88
|
|
|
|
|
|
|
system by first checking for conf files and then falling back to check |
|
89
|
|
|
|
|
|
|
the master boot record. |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
Possible return values: |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
grub grub was determined to be the bootloader in use |
|
94
|
|
|
|
|
|
|
lilo lilo was determined to be is the bootloader in use |
|
95
|
|
|
|
|
|
|
elilo elilo was determined to be the bootloader in use |
|
96
|
|
|
|
|
|
|
yaboot yaboot was determined to be the bootloader in use |
|
97
|
|
|
|
|
|
|
undef it was impossible to determine which bootloader was being used |
|
98
|
|
|
|
|
|
|
due either to configuration files for multiple bootloaders or |
|
99
|
|
|
|
|
|
|
bootloader on multiple hard disks |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=cut |
|
102
|
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub detect_bootloader { |
|
104
|
1
|
|
33
|
1
|
1
|
7
|
return detect_bootloader_from_conf(@_) |
|
105
|
|
|
|
|
|
|
|| detect_bootloader_from_mbr(@_); |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=head2 detect_bootloader_from_conf() |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Detects bootloaders by the presence of config files. This is not as |
|
111
|
|
|
|
|
|
|
reliable of a mechanism as looking in the MBR, but tends to be |
|
112
|
|
|
|
|
|
|
significantly faster. |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
If called in list context, it will return a list of the bootloaders that |
|
115
|
|
|
|
|
|
|
it found. |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
If called in scalar context and only a single bootloader config file is |
|
118
|
|
|
|
|
|
|
present it will return the name of that bootloader. Otherwise, if |
|
119
|
|
|
|
|
|
|
multiple (or no) bootloaders are detected, it will return undef. |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=cut |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub detect_bootloader_from_conf { |
|
124
|
2
|
|
|
2
|
1
|
9
|
my @boot_loader = (); |
|
125
|
|
|
|
|
|
|
|
|
126
|
2
|
|
|
|
|
170
|
my %boot_list = ( grub => '/boot/grub/menu.lst', |
|
127
|
|
|
|
|
|
|
lilo => '/etc/lilo.conf', |
|
128
|
|
|
|
|
|
|
elilo => '/etc/elilo.conf', |
|
129
|
|
|
|
|
|
|
yaboot => '/etc/yaboot.conf' |
|
130
|
|
|
|
|
|
|
); |
|
131
|
|
|
|
|
|
|
|
|
132
|
2
|
|
|
|
|
14
|
foreach my $key ( sort keys %boot_list ) { |
|
133
|
8
|
50
|
|
|
|
370
|
if ( -f $boot_list{$key} ) { |
|
134
|
0
|
|
|
|
|
0
|
push ( @boot_loader, $key ); |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
2
|
100
|
|
|
|
15
|
if (wantarray()) { |
|
|
|
50
|
|
|
|
|
|
|
139
|
1
|
|
|
|
|
9
|
return @boot_loader; |
|
140
|
|
|
|
|
|
|
} elsif (@boot_loader == 1) { |
|
141
|
0
|
|
|
|
|
0
|
return pop( @boot_loader ); |
|
142
|
|
|
|
|
|
|
} else { |
|
143
|
1
|
|
|
|
|
12
|
return undef; |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head2 detect_bootloader_from_mbr([@devices]) |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
Detects the bootloader by scanning the master boot record (MBR) of the |
|
150
|
|
|
|
|
|
|
specified devices (or all devices if not indicated). |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
The device arguments must be relative to the /dev/ directory. I.e., |
|
153
|
|
|
|
|
|
|
('hda', 'sdb', 'cdroms/cdrom0', etc.) |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=cut |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub detect_bootloader_from_mbr { |
|
158
|
2
|
|
|
2
|
1
|
2366
|
my @filelist = @_; |
|
159
|
2
|
|
|
|
|
19
|
my @boot_loader = (); |
|
160
|
|
|
|
|
|
|
|
|
161
|
2
|
|
|
|
|
35
|
my %map = ( |
|
162
|
|
|
|
|
|
|
"GRUB" => 'grub', |
|
163
|
|
|
|
|
|
|
"LILO" => 'lilo', |
|
164
|
|
|
|
|
|
|
"EFI" => 'elilo', |
|
165
|
|
|
|
|
|
|
"yaboot" => 'yaboot', |
|
166
|
|
|
|
|
|
|
); |
|
167
|
|
|
|
|
|
|
|
|
168
|
2
|
50
|
33
|
|
|
133
|
if ( ! @filelist && opendir( DIRH, "/sys/block" ) ) { |
|
169
|
2
|
|
|
|
|
65
|
@filelist = grep { /^[sh]d.$/ } readdir(DIRH); |
|
|
60
|
|
|
|
|
357
|
|
|
170
|
2
|
|
|
|
|
38
|
closedir(DIRH); |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
|
|
173
|
2
|
|
|
|
|
8
|
foreach ( @filelist ) { |
|
174
|
0
|
0
|
|
|
|
0
|
if ( -b "/dev/$_" ) { |
|
175
|
0
|
|
|
|
|
0
|
my $strings = `dd if=/dev/$_ bs=512 count=1 2>/dev/null | strings`; |
|
176
|
0
|
|
|
|
|
0
|
foreach my $loader (keys %map) { |
|
177
|
0
|
0
|
|
|
|
0
|
if ($strings =~ /$loader/ms) { |
|
178
|
0
|
|
|
|
|
0
|
push @boot_loader, $map{$loader}; |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
2
|
50
|
|
|
|
22
|
if (wantarray()) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Show them all |
|
186
|
0
|
|
|
|
|
0
|
return @boot_loader; |
|
187
|
|
|
|
|
|
|
} elsif (@boot_loader == 1) { |
|
188
|
|
|
|
|
|
|
# Found exactly one |
|
189
|
0
|
|
|
|
|
0
|
return pop @boot_loader; |
|
190
|
|
|
|
|
|
|
} elsif (@boot_loader == 2) { |
|
191
|
|
|
|
|
|
|
# This is the Lilo/Grub exception |
|
192
|
|
|
|
|
|
|
# Grub on MBR with previous Lilo install |
|
193
|
|
|
|
|
|
|
# Are they lilo and grub in that order? |
|
194
|
0
|
0
|
0
|
|
|
0
|
if ($boot_loader[0] eq 'lilo' and $boot_loader[1] eq 'grub'){ |
|
195
|
0
|
|
|
|
|
0
|
warn "Warning: Grub appears to be used currently, but Lilo was in pasti.\n"; |
|
196
|
0
|
|
|
|
|
0
|
return $boot_loader[1]; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# Either none or too many to choose from |
|
201
|
2
|
|
|
|
|
21
|
return undef; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
1; |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head1 AUTHOR |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Open Source Development Labs, Engineering Department |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
Copyright (C) 2006 Open Source Development Labs |
|
213
|
|
|
|
|
|
|
All Rights Reserved. |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
This script is free software; you can redistribute it and/or modify it |
|
216
|
|
|
|
|
|
|
under the same terms as Perl itself. |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
L |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=cut |
|
223
|
|
|
|
|
|
|
|