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
|
|
|
|
|
|
|
|