]>
code.delx.au - refind/blob - gptsync/showpart.c
3 * Platform-independent code for analyzing hard disk partitioning
5 * Copyright (c) 2006 Christoph Pfisterer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the
20 * * Neither the name of Christoph Pfisterer nor the names of the
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 // memory string search
43 static INTN
FindMem(VOID
*Buffer
, UINTN BufferLength
, VOID
*SearchString
, UINTN SearchStringLength
)
49 BufferLength
-= SearchStringLength
;
50 for (Offset
= 0; Offset
< BufferLength
; Offset
++, BufferPtr
++) {
51 if (CompareMem(BufferPtr
, SearchString
, SearchStringLength
) == 0)
62 static UINTN
detect_bootcode(UINT64 partlba
, CHARN
**bootcodename
)
68 status
= read_sector(partlba
, sector
);
72 // check bootable signature
73 if (*((UINT16
*)(sector
+ 510)) == 0xaa55 && sector
[0] != 0)
79 // detect specific boot codes
80 if (CompareMem(sector
+ 2, "LILO", 4) == 0 ||
81 CompareMem(sector
+ 6, "LILO", 4) == 0) {
82 *bootcodename
= STR("LILO");
84 } else if (CompareMem(sector
+ 3, "SYSLINUX", 8) == 0) {
85 *bootcodename
= STR("SYSLINUX");
87 } else if (FindMem(sector
, 512, "ISOLINUX", 8) >= 0) {
88 *bootcodename
= STR("ISOLINUX");
90 } else if (FindMem(sector
, 512, "Geom\0Hard Disk\0Read\0 Error", 26) >= 0) {
91 *bootcodename
= STR("GRUB");
93 } else if ((*((UINT32
*)(sector
+ 502)) == 0 &&
94 *((UINT32
*)(sector
+ 506)) == 50000 &&
95 *((UINT16
*)(sector
+ 510)) == 0xaa55) ||
96 FindMem(sector
, 512, "Starting the BTX loader", 23) >= 0) {
97 *bootcodename
= STR("FreeBSD");
99 } else if (FindMem(sector
, 512, "!Loading", 8) >= 0 ||
100 FindMem(sector
, 512, "/cdboot\0/CDBOOT\0", 16) >= 0) {
101 *bootcodename
= STR("OpenBSD");
103 } else if (FindMem(sector
, 512, "Not a bootxx image", 18) >= 0) {
104 *bootcodename
= STR("NetBSD");
106 } else if (FindMem(sector
, 512, "NTLDR", 5) >= 0) {
107 *bootcodename
= STR("Windows NTLDR");
109 } else if (FindMem(sector
, 512, "BOOTMGR", 7) >= 0) {
110 *bootcodename
= STR("Windows BOOTMGR (Vista)");
112 } else if (FindMem(sector
, 512, "CPUBOOT SYS", 11) >= 0 ||
113 FindMem(sector
, 512, "KERNEL SYS", 11) >= 0) {
114 *bootcodename
= STR("FreeDOS");
116 } else if (FindMem(sector
, 512, "OS2LDR", 6) >= 0 ||
117 FindMem(sector
, 512, "OS2BOOT", 7) >= 0) {
118 *bootcodename
= STR("eComStation");
120 } else if (FindMem(sector
, 512, "Be Boot Loader", 14) >= 0) {
121 *bootcodename
= STR("BeOS");
123 } else if (FindMem(sector
, 512, "yT Boot Loader", 14) >= 0) {
124 *bootcodename
= STR("ZETA");
126 } else if (FindMem(sector
, 512, "\x04" "beos\x06" "system\x05" "zbeos", 18) >= 0) {
127 *bootcodename
= STR("Haiku");
131 if (FindMem(sector
, 512, "Non-system disk", 15) >= 0) // dummy FAT boot sector
132 *bootcodename
= STR("None (Non-system disk message)");
134 // TODO: Add a note if a specific code was detected, but the sector is not bootable?
136 if (*bootcodename
== NULL
) {
138 *bootcodename
= STR("Unknown, but bootable");
140 *bootcodename
= STR("None");
147 // check one partition
150 static UINTN
analyze_part(UINT64 partlba
)
159 Print(L
"\nMBR contents:\n");
161 Print(L
"\nPartition at LBA %lld:\n", partlba
);
164 status
= detect_bootcode(partlba
, &bootcodename
);
167 Print(L
" Boot Code: %s\n", bootcodename
);
170 return 0; // short-circuit MBR analysis
172 // detect file system
173 status
= detect_mbrtype_fs(partlba
, &parttype
, &fsname
);
176 Print(L
" File System: %s\n", fsname
);
178 // cross-reference with partition table
179 for (i
= 0; i
< gpt_part_count
; i
++) {
180 if (gpt_parts
[i
].start_lba
== partlba
) {
181 Print(L
" Listed in GPT as partition %d, type %s\n", i
+1,
182 gpt_parts
[i
].gpt_parttype
->name
);
185 for (i
= 0; i
< mbr_part_count
; i
++) {
186 if (mbr_parts
[i
].start_lba
== partlba
) {
187 Print(L
" Listed in MBR as partition %d, type %02x %s%s\n", i
+1,
188 mbr_parts
[i
].mbr_type
,
189 mbr_parttype_name(mbr_parts
[i
].mbr_type
),
190 mbr_parts
[i
].active
? STR(", active") : STR(""));
198 // check all partitions
201 static UINTN
analyze_parts(VOID
)
207 // check MBR (bootcode only)
208 status
= analyze_part(0);
212 // check partitions listed in GPT
213 for (i
= 0; i
< gpt_part_count
; i
++) {
214 status
= analyze_part(gpt_parts
[i
].start_lba
);
219 // check partitions listed in MBR, but not in GPT
220 for (i
= 0; i
< mbr_part_count
; i
++) {
221 if (mbr_parts
[i
].start_lba
== 1 && mbr_parts
[i
].mbr_type
== 0xee)
222 continue; // skip EFI Protective entry
225 for (k
= 0; k
< gpt_part_count
; k
++)
226 if (gpt_parts
[k
].start_lba
== mbr_parts
[i
].start_lba
)
230 status
= analyze_part(mbr_parts
[i
].start_lba
);
240 // display algorithm entry point
246 UINTN status_gpt
, status_mbr
;
248 // get full information from disk
249 status_gpt
= read_gpt();
250 status_mbr
= read_mbr();
251 if (status_gpt
!= 0 || status_mbr
!= 0)
252 return (status_gpt
|| status_mbr
);
254 // analyze all partitions
255 status
= analyze_parts();