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