1 /* $NetBSD: md.c,v 1.22 2022/01/29 16:01:17 martin Exp $ */ 2 3 /* 4 * Copyright 1997 Piermont Information Systems Inc. 5 * All rights reserved. 6 * 7 * Based on code written by Philip A. Nelson for Piermont Information 8 * Systems Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. 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 distribution. 18 * 3. The name of Piermont Information Systems Inc. may not be used to endorse 19 * or promote products derived from this software without specific prior 20 * written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 32 * THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* md.c -- shark machine specific routines */ 36 37 #include <stdio.h> 38 #include <curses.h> 39 #include <unistd.h> 40 #include <fcntl.h> 41 #include <util.h> 42 #include <sys/types.h> 43 #include <sys/ioctl.h> 44 #include <sys/param.h> 45 #include <sys/sysctl.h> 46 47 #include "defs.h" 48 #include "md.h" 49 #include "msg_defs.h" 50 #include "menu_defs.h" 51 52 int boardtype = BOARD_TYPE_NORMAL; 53 54 #define SBSA_MODEL_STR "netbsd,generic-acpi" 55 #define RPI_MODEL_STR "raspberrypi," 56 57 void 58 md_init(void) 59 { 60 static const int mib[2] = {CTL_HW, HW_MODEL}; 61 size_t len; 62 char *cpu_model; 63 64 sysctl(mib, 2, NULL, &len, NULL, 0); 65 cpu_model = malloc(len); 66 sysctl(mib, 2, cpu_model, &len, NULL, 0); 67 68 if (strstr(cpu_model, RPI_MODEL_STR) != NULL) 69 /* this is some kind of Raspberry Pi */ 70 boardtype = BOARD_TYPE_RPI; 71 else if (strstr(cpu_model, SBSA_MODEL_STR) != NULL) 72 /* some SBSA compatible machine */ 73 boardtype = BOARD_TYPE_ACPI; 74 else 75 /* unknown, assume u-boot + dtb */ 76 boardtype = BOARD_TYPE_NORMAL; 77 78 free(cpu_model); 79 } 80 81 void 82 md_init_set_status(int flags) 83 { 84 85 /* 86 * we will extract kernel variants piecewise manually 87 * later, just fetch the kernel set, do not unpack it. 88 */ 89 set_kernel_set(SET_KERNEL_1); 90 set_noextract_set(SET_KERNEL_1); 91 } 92 93 bool 94 md_get_info(struct install_partition_desc *install) 95 { 96 int res; 97 98 if (pm->no_mbr || pm->no_part) 99 return true; 100 101 again: 102 if (pm->parts == NULL) { 103 104 const struct disk_partitioning_scheme *ps = 105 select_part_scheme(pm, NULL, true, NULL); 106 107 if (!ps) 108 return false; 109 110 struct disk_partitions *parts = 111 (*ps->create_new_for_disk)(pm->diskdev, 112 0, pm->dlsize, true, NULL); 113 if (!parts) 114 return false; 115 116 pm->parts = parts; 117 if (ps->size_limit > 0 && pm->dlsize > ps->size_limit) 118 pm->dlsize = ps->size_limit; 119 } 120 121 /* 122 * If the selected scheme does not need two-stage partitioning 123 * (like GPT), do not bother to edit the outer partitions. 124 */ 125 if (pm->parts->pscheme->secondary_partitions == NULL || 126 pm->parts->pscheme->secondary_scheme == NULL) 127 return true; 128 129 res = edit_outer_parts(pm->parts); 130 if (res == 0) 131 return false; 132 else if (res == 1) 133 return true; 134 135 pm->parts->pscheme->destroy_part_scheme(pm->parts); 136 pm->parts = NULL; 137 goto again; 138 } 139 140 /* 141 * md back-end code for menu-driven BSD disklabel editor. 142 */ 143 int 144 md_make_bsd_partitions(struct install_partition_desc *install) 145 { 146 return make_bsd_partitions(install); 147 } 148 149 /* 150 * any additional partition validation 151 */ 152 bool 153 md_check_partitions(struct install_partition_desc *install) 154 { 155 size_t i; 156 157 for (i = 0; i < install->num; i++) 158 if (install->infos[i].fs_type == FS_MSDOS) 159 return true; 160 161 msg_display(MSG_nomsdospart); 162 process_menu(MENU_ok, NULL); 163 164 return false; 165 } 166 167 /* 168 * hook called before writing new disklabel. 169 */ 170 bool 171 md_pre_disklabel(struct install_partition_desc *install, 172 struct disk_partitions *parts) 173 { 174 175 /* 176 * RAW_PART is 2 on evbarm and bad things happen if we 177 * write the MBR first and then the disklabel - so postpone 178 * the MBR to md_post_disklabel(), unlike other architecturs. 179 */ 180 return true; 181 } 182 183 /* 184 * hook called after writing disklabel to new target disk. 185 */ 186 bool 187 md_post_disklabel(struct install_partition_desc *install, 188 struct disk_partitions *parts) 189 { 190 if (parts->parent == NULL) 191 return true; /* no outer partitions */ 192 193 parts = parts->parent; 194 195 msg_display_subst(MSG_dofdisk, 3, parts->disk, 196 msg_string(parts->pscheme->name), 197 msg_string(parts->pscheme->short_name)); 198 199 /* write edited "MBR" onto disk. */ 200 if (!parts->pscheme->write_to_disk(parts)) { 201 msg_display(MSG_wmbrfail); 202 process_menu(MENU_ok, NULL); 203 return false; 204 } 205 return true; 206 } 207 208 /* 209 * hook called after upgrade() or install() has finished setting 210 * up the target disk but immediately before the user is given the 211 * ``disks are now set up'' message. 212 */ 213 int 214 md_post_newfs(struct install_partition_desc *install) 215 { 216 return 0; 217 } 218 219 int 220 evbarm_extract_finalize(int update) 221 { 222 distinfo *dist; 223 char kernelbin[100]; 224 int (*saved_fetch_fn)(const char *); 225 #ifdef _LP64 226 #define EFIBOOT "/usr/mdec/bootaa64.efi" 227 #else 228 #define EFIBOOT "/usr/mdec/bootarm.efi" 229 #endif 230 231 dist = get_set_distinfo(SET_KERNEL_1); 232 if (dist == NULL) 233 return 0; 234 235 saved_fetch_fn = fetch_fn; 236 extract_file_to(dist, false, "/", "./netbsd", false); 237 fetch_fn = NULL; 238 make_target_dir("/boot/EFI/boot"); 239 if (target_file_exists_p(EFIBOOT)) 240 cp_within_target(EFIBOOT, "/boot/EFI/boot", 0); 241 242 if (boardtype == BOARD_TYPE_ACPI) { 243 fetch_fn = saved_fetch_fn; 244 return 0; 245 } 246 if (boardtype == BOARD_TYPE_NORMAL) { 247 extract_file_to(dist, false, "/boot", "./netbsd.ub", false); 248 fetch_fn = saved_fetch_fn; 249 return 0; 250 } 251 if (boardtype == BOARD_TYPE_RPI) { 252 extract_file_to(dist, false, "/boot", "./netbsd.img", false); 253 fetch_fn = saved_fetch_fn; 254 snprintf(kernelbin, 100, "%s/netbsd.img", targetroot_mnt); 255 if (file_exists_p(kernelbin)) { 256 run_program(RUN_DISPLAY, 257 "/bin/cp %s /targetroot/boot/kernel.img", kernelbin); 258 } else { 259 msg_display(MSG_rpikernelmissing); 260 process_menu(MENU_ok, NULL); 261 return 1; 262 } 263 } 264 fetch_fn = saved_fetch_fn; 265 return 0; 266 } 267 268 int 269 md_post_extract(struct install_partition_desc *install, bool upgrade) 270 { 271 272 return 0; 273 } 274 275 void 276 md_cleanup_install(struct install_partition_desc *install) 277 { 278 #ifndef DEBUG 279 enable_rc_conf(); 280 add_rc_conf("sshd=YES\n"); 281 add_rc_conf("dhcpcd=YES\n"); 282 #endif 283 } 284 285 int 286 md_pre_update(struct install_partition_desc *install) 287 { 288 return 1; 289 } 290 291 /* Upgrade support */ 292 int 293 md_update(struct install_partition_desc *install) 294 { 295 md_post_newfs(install); 296 return 1; 297 } 298 299 int 300 md_pre_mount(struct install_partition_desc *install, size_t ndx) 301 { 302 return 0; 303 } 304 305 int 306 md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet) 307 { 308 mbr_info_t *ext; 309 struct mbr_partition *part; 310 int i, hasboot=0; 311 312 for (ext = mbri; ext; ext = ext->extended) { 313 part = ext->mbr.mbr_parts; 314 for (i=0, hasboot=0; i < MBR_PART_COUNT; part++, i++) { 315 if (part->mbrp_type != MBR_PTYPE_FAT16L && 316 part->mbrp_type != MBR_PTYPE_FAT32L) 317 continue; 318 hasboot = 1; 319 break; 320 } 321 } 322 if (!hasboot) { 323 if (quiet) 324 return 2; 325 msg_display(MSG_nomsdospart); 326 return ask_reedit(parts); 327 } 328 329 return 2; 330 } 331 332 bool 333 md_parts_use_wholedisk(struct disk_partitions *parts) 334 { 335 struct disk_part_info boot_part = { 336 .size = boardtype == BOARD_TYPE_NORMAL ? 337 PART_BOOT_LARGE/parts->bytes_per_sector : 338 PART_BOOT/parts->bytes_per_sector, 339 .fs_type = PART_BOOT_TYPE, 340 .fs_sub_type = boardtype == BOARD_TYPE_NORMAL ? 341 MBR_PTYPE_FAT32L : MBR_PTYPE_FAT16L, 342 }; 343 344 return parts_use_wholedisk(parts, 1, &boot_part); 345 } 346 347 /* returns false if no write-back of parts is required */ 348 bool 349 md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri) 350 { 351 return false; 352 } 353 354 #ifdef HAVE_GPT 355 /* 356 * New GPT partitions have been written, update bootloader or remember 357 * data untill needed in md_post_newfs 358 */ 359 bool 360 md_gpt_post_write(struct disk_partitions *parts, part_id root_id, 361 bool root_is_new, part_id efi_id, bool efi_is_new) 362 { 363 return true; 364 } 365 #endif 366 367 void 368 evbarm_part_defaults(struct pm_devs *my_pm, struct part_usage_info *infos, 369 size_t num_usage_infos) 370 { 371 size_t i; 372 373 for (i = 0; i < num_usage_infos; i++) { 374 if (infos[i].fs_type == PART_BOOT_TYPE && 375 infos[i].mount[0] != 0 && 376 strcmp(infos[i].mount, PART_BOOT_MOUNT) == 0) { 377 infos[i].size = boardtype == BOARD_TYPE_NORMAL ? 378 PART_BOOT_LARGE/my_pm->parts->bytes_per_sector : 379 PART_BOOT/my_pm->parts->bytes_per_sector; 380 infos[i].fs_version = boardtype == BOARD_TYPE_NORMAL ? 381 MBR_PTYPE_FAT32L : MBR_PTYPE_FAT16L; 382 return; 383 } 384 } 385 } 386 387