1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 2009 Pierre-Alexandre Meyer - All Rights Reserved
4 *
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom
11 * the Software is furnished to do so, subject to the following
12 * conditions:
13 *
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * -----------------------------------------------------------------------
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <errno.h>
33
34 #include "hdt-cli.h"
35 #include "hdt-common.h"
36 #include "hdt-util.h"
37
38 /**
39 * show_partition_information - print information about a partition
40 * @ptab: part_entry describing the partition
41 * @i: Partition number (UI purposes only)
42 * @ptab_root: part_entry describing the root partition (extended only)
43 * @drive_info: driveinfo struct describing the drive on which the partition
44 * is
45 *
46 * Note on offsets (from hpa, see chain.c32):
47 *
48 * To make things extra confusing: data partition offsets are relative to where
49 * the data partition record is stored, whereas extended partition offsets
50 * are relative to the beginning of the extended partition all the way back
51 * at the MBR... but still not absolute!
52 **/
show_partition_information(struct driveinfo * drive_info,struct part_entry * ptab,int partition_offset,int nb_partitions_seen)53 static void show_partition_information(struct driveinfo *drive_info,
54 struct part_entry *ptab,
55 int partition_offset,
56 int nb_partitions_seen)
57 {
58 char size[11];
59 char bootloader_name[9];
60 char *parttype;
61 unsigned int start, end;
62
63 int i = nb_partitions_seen;
64
65 reset_more_printf();
66
67 start = partition_offset;
68 end = start + ptab->length - 1;
69
70 if (ptab->length > 0)
71 sectors_to_size(ptab->length, size);
72 else
73 memset(size, 0, sizeof size);
74
75 if (i == 1)
76 more_printf(" # B Start End Size Id Type\n");
77
78 get_label(ptab->ostype, &parttype);
79 more_printf("%2d %s %11d %11d %s %02X %s",
80 i, (ptab->active_flag == 0x80) ? "x" : " ",
81 start, end, size, ptab->ostype, parttype);
82
83 /* Extra info */
84 if (ptab->ostype == 0x82 && swsusp_check(drive_info, ptab))
85 more_printf("%s", " (Swsusp sig. detected)");
86
87 if (get_bootloader_string(drive_info, ptab, bootloader_name, 9) == 0)
88 more_printf("%-46s %s %s", " ", "Bootloader:", bootloader_name);
89
90 more_printf("\n");
91
92 free(parttype);
93 }
94
main_show_disk(int argc,char ** argv,struct s_hardware * hardware)95 void main_show_disk(int argc, char **argv, struct s_hardware *hardware)
96 {
97 if (!argc) {
98 more_printf("Which disk?\n");
99 return;
100 }
101
102 int drive = strtol(argv[0], (char **)NULL, 16);
103
104 if (drive < 0x80 || drive >= 0xff) {
105 more_printf("Invalid disk: %d.\n", drive);
106 return;
107 }
108
109 int i = drive - 0x80;
110 struct driveinfo *d = &hardware->disk_info[i];
111 char disk_size[11];
112 char mbr_name[50];
113
114 reset_more_printf();
115
116 if (!hardware->disk_info[i].cbios) {
117 more_printf("No disk found\n");
118 return; /* Invalid geometry */
119 }
120
121 get_mbr_string(hardware->mbr_ids[i], &mbr_name, 50);
122
123 if ((int)d->edd_params.sectors > 0)
124 sectors_to_size((int)d->edd_params.sectors, disk_size);
125 else
126 memset(disk_size, 0, sizeof disk_size);
127
128 more_printf("DISK 0x%X:\n"
129 " C/H/S: %d cylinders, %d heads, %d sectors/track\n"
130 " EDD: Version: %X\n"
131 " Size: %s, %d bytes/sector, %d sectors/track\n"
132 " Host bus: %s, Interface type: %s\n"
133 " MBR: %s (id 0x%X)\n\n",
134 d->disk,
135 d->legacy_max_cylinder + 1, d->legacy_max_head + 1,
136 d->legacy_sectors_per_track, d->edd_version, disk_size,
137 (int)d->edd_params.bytes_per_sector,
138 (int)d->edd_params.sectors_per_track,
139 remove_spaces((char *)d->edd_params.host_bus_type),
140 remove_spaces((char *)d->edd_params.interface_type), mbr_name,
141 hardware->mbr_ids[i]);
142 display_line_nb += 6;
143
144 if (parse_partition_table(d, &show_partition_information)) {
145 if (errno_disk) {
146 fprintf(stderr, "I/O error parsing disk 0x%X\n", d->disk);
147 get_error("parse_partition_table");
148 } else {
149 fprintf(stderr, "Disk 0x%X: unrecognized partition layout\n",
150 d->disk);
151 }
152 fprintf(stderr, "\n");
153 }
154
155 more_printf("\n");
156 }
157
main_show_disks(int argc __unused,char ** argv __unused,struct s_hardware * hardware)158 void main_show_disks(int argc __unused, char **argv __unused,
159 struct s_hardware *hardware)
160 {
161 bool found = false;
162 reset_more_printf();
163
164 int first_one = 0;
165 for (int drive = 0x80; drive < 0xff; drive++) {
166 if (hardware->disk_info[drive - 0x80].cbios) {
167 found = true;
168 if (!first_one) {
169 first_one = 1;
170 } else {
171 pause_printf();
172 }
173 char buf[5] = "";
174 sprintf(buf, "0x%x", drive);
175 char *argv[1] = { buf };
176 main_show_disk(1, argv, hardware);
177 }
178 }
179
180 if (found == false)
181 more_printf("No disk found\n");
182 }
183
disks_summary(int argc __unused,char ** argv __unused,struct s_hardware * hardware)184 void disks_summary(int argc __unused, char **argv __unused,
185 struct s_hardware *hardware)
186 {
187 int i = -1;
188 bool found = false;
189
190 reset_more_printf();
191
192 for (int drive = 0x80; drive < 0xff; drive++) {
193 i++;
194 if (!hardware->disk_info[i].cbios)
195 continue; /* Invalid geometry */
196
197 found = true;
198 struct driveinfo *d = &hardware->disk_info[i];
199 char disk_size[11];
200
201 if ((int)d->edd_params.sectors > 0)
202 sectors_to_size((int)d->edd_params.sectors, disk_size);
203 else
204 memset(disk_size, 0, sizeof disk_size);
205
206 more_printf("DISK 0x%X:\n", d->disk);
207 more_printf(" C/H/S: %d cylinders, %d heads, %d sectors/track\n",
208 d->legacy_max_cylinder + 1, d->legacy_max_head + 1,
209 d->legacy_sectors_per_track);
210 more_printf(" EDD: Version: %X, size: %s\n", d->edd_version,
211 disk_size);
212
213 /* Do not print Host Bus & Interface if EDD isn't 3.0 or more */
214 if (d->edd_version >= 0x30)
215 more_printf(" Host bus: %s, Interface type: %s\n\n",
216 remove_spaces((char *)d->edd_params.host_bus_type),
217 remove_spaces((char *)d->edd_params.interface_type));
218 }
219
220 if (found == false)
221 more_printf("No disk found\n");
222 }
223
224 struct cli_callback_descr list_disk_show_modules[] = {
225 {
226 .name = "disks",
227 .exec = main_show_disks,
228 .nomodule = false,
229 },
230 {
231 .name = "disk",
232 .exec = main_show_disk,
233 .nomodule = false,
234 },
235 {
236 .name = NULL,
237 .exec = NULL,
238 .nomodule = false,
239 },
240 };
241
242 struct cli_module_descr disk_show_modules = {
243 .modules = list_disk_show_modules,
244 .default_callback = disks_summary,
245 };
246
247 struct cli_mode_descr disk_mode = {
248 .mode = DISK_MODE,
249 .name = CLI_DISK,
250 .default_modules = NULL,
251 .show_modules = &disk_show_modules,
252 .set_modules = NULL,
253 };
254