1/* $NetBSD: md.c,v 1.16 2022/06/11 16:25:23 tsutsui 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 -- cobalt machine specific routines */ 36 37#include <sys/param.h> 38#include <sys/sysctl.h> 39#include <stdio.h> 40#include <util.h> 41#include <machine/cpu.h> 42 43#include "defs.h" 44#include "md.h" 45#include "msg_defs.h" 46#include "menu_defs.h" 47 48/* 49 * Firmware reognizes only Linux Ext2 REV 0, so we have to have 50 * a Linux Ext2 fs to store our native bootloader. 51 */ 52static int nobootfs = 0; 53 54void 55md_init(void) 56{ 57} 58 59void 60md_init_set_status(int flags) 61{ 62 (void)flags; 63} 64 65bool 66md_get_info(struct install_partition_desc *install) 67{ 68 int res; 69 70 if (pm->no_mbr || pm->no_part) 71 return true; 72 73again: 74 if (pm->parts == NULL) { 75 76 const struct disk_partitioning_scheme *ps = 77 select_part_scheme(pm, NULL, true, NULL); 78 79 if (!ps) 80 return false; 81 82 struct disk_partitions *parts = 83 (*ps->create_new_for_disk)(pm->diskdev, 84 0, pm->dlsize, true, NULL); 85 if (!parts) 86 return false; 87 88 pm->parts = parts; 89 if (ps->size_limit > 0 && pm->dlsize > ps->size_limit) 90 pm->dlsize = ps->size_limit; 91 } 92 93 res = set_bios_geom_with_mbr_guess(pm->parts); 94 if (res == 0) 95 return false; 96 else if (res == 1) 97 return true; 98 99 pm->parts->pscheme->destroy_part_scheme(pm->parts); 100 pm->parts = NULL; 101 goto again; 102} 103 104/* 105 * md back-end code for menu-driven BSD disklabel editor. 106 */ 107int 108md_make_bsd_partitions(struct install_partition_desc *install) 109{ 110 return make_bsd_partitions(install); 111} 112 113/* 114 * any additional partition validation 115 */ 116bool 117md_check_partitions(struct install_partition_desc *install) 118{ 119 size_t part; 120 121 /* we need to find a boot partition, otherwise we can't write our 122 * bootloader. We make the assumption that the user hasn't done 123 * something stupid, like move it away from the MBR partition. 124 */ 125 for (part = 0; part < install->num; part++) { 126 if (install->infos[part].fs_type == PART_BOOT_TYPE) 127 return true; 128 } 129 130 msg_display(MSG_nobootpartdisklabel); 131 process_menu(MENU_ok, NULL); 132 return false; 133} 134 135/* 136 * hook called before writing new disklabel. 137 */ 138bool 139md_pre_disklabel(struct install_partition_desc *install, 140 struct disk_partitions *parts) 141{ 142 143 if (parts->parent == NULL) 144 return true; /* no outer partitions */ 145 146 parts = parts->parent; 147 148 msg_display_subst(MSG_dofdisk, 3, parts->disk, 149 msg_string(parts->pscheme->name), 150 msg_string(parts->pscheme->short_name)); 151 152 /* write edited "MBR" onto disk. */ 153 if (!parts->pscheme->write_to_disk(parts)) { 154 msg_display(MSG_wmbrfail); 155 process_menu(MENU_ok, NULL); 156 return false; 157 } 158 return true; 159} 160 161/* 162 * hook called after writing disklabel to new target disk. 163 */ 164bool 165md_post_disklabel(struct install_partition_desc *install, 166 struct disk_partitions *parts) 167{ 168 return true; 169} 170 171/* 172 * hook called after upgrade() or install() has finished setting 173 * up the target disk but immediately before the user is given the 174 * ``disks are now set up'' message. 175 */ 176int 177md_post_newfs(struct install_partition_desc *install) 178{ 179 static const char *kernels[] = { 180 "vmlinux-nfsroot.gz", 181 "vmlinux.gz", 182 "vmlinux_RAQ.gz", 183 "vmlinux_raq-2800.gz" 184 }; 185 static const char *bootfile = "boot.gz"; 186 char bootdir[64]; 187 unsigned int i; 188 189 if (!nobootfs) { 190 msg_fmt_display(msg_string(MSG_copybootloader), "%s", 191 pm->diskdev); 192 193 snprintf(bootdir, sizeof(bootdir), "%s/boot", 194 target_expand(PART_BOOT_MOUNT)); 195 run_program(0, "/bin/mkdir -p %s", bootdir); 196 run_program(0, "/bin/cp /usr/mdec/boot %s", bootdir); 197 run_program(0, "/bin/rm -f %s/%s", bootdir, bootfile); 198 run_program(0, "/usr/bin/gzip -9 %s/boot", bootdir); 199 for (i = 0; i < __arraycount(kernels); i++) 200 run_program(0, "/bin/ln -fs %s %s/%s", 201 bootfile, bootdir, kernels[i]); 202 } 203 204 return 0; 205} 206 207int 208md_post_extract(struct install_partition_desc *install, bool upgrade) 209{ 210 return 0; 211} 212 213void 214md_cleanup_install(struct install_partition_desc *install) 215{ 216#ifndef DEBUG 217 enable_rc_conf(); 218#endif 219} 220 221int 222md_pre_update(struct install_partition_desc *install) 223{ 224 size_t i; 225 226 /* 227 * Verify the msdos partition exists and is big enough. 228 */ 229 for (i = 0; i < install->num; i++) { 230 if (install->infos[i].fs_type != PART_BOOT_TYPE) 231 continue; 232 if (install->infos[i].size/512 >= PART_BOOT_MIN) 233 break; 234 msg_display(MSG_boottoosmall); 235 msg_fmt_display_add(MSG_nobootpart, "%d", 0); 236 if (!ask_yesno(NULL)) 237 return false; 238 nobootfs = 1; 239 break; 240 } 241 242 if (md_check_partitions(install) == 0) 243 nobootfs = 1; 244 245 return 1; 246} 247 248/* Upgrade support */ 249int 250md_update(struct install_partition_desc *install) 251{ 252 md_post_newfs(install); 253 return 1; 254} 255 256int 257md_check_mbr(struct disk_partitions *parts, mbr_info_t *mbri, bool quiet) 258{ 259 mbr_info_t *ext; 260 struct mbr_partition *part; 261 int i; 262 263 for (ext = mbri; ext; ext = ext->extended) { 264 part = ext->mbr.mbr_parts; 265 for (i = 0; i < MBR_PART_COUNT; part++, i++) { 266 if (part->mbrp_type == MBR_PTYPE_LNXEXT2) { 267 pm->bootstart = part->mbrp_start; 268 pm->bootsize = part->mbrp_size; 269 break; 270 } 271 } 272 } 273 if (pm->bootsize < (PART_BOOT_MIN / 512)) { 274 if (quiet) 275 return 0; 276 msg_display(MSG_boottoosmall); 277 return ask_reedit(parts); 278 } 279 if (pm->bootstart == 0 || pm->bootsize == 0) { 280 if (quiet) 281 return 0; 282 msg_display(MSG_nobootpart); 283 return ask_reedit(parts); 284 } 285 return 2; 286} 287 288bool 289md_parts_use_wholedisk(struct disk_partitions *parts) 290{ 291 struct disk_part_info boot_part = { 292 .size = PART_BOOT / 512, 293 .fs_type = PART_BOOT_TYPE, 294 .fs_sub_type = MBR_PTYPE_LNXEXT2, 295 .last_mounted = PART_BOOT_MOUNT, 296 }; 297 298 boot_part.nat_type = parts->pscheme->get_fs_part_type( 299 PT_EXT2, boot_part.fs_type, boot_part.fs_sub_type); 300 301 return parts_use_wholedisk(parts, 1, &boot_part); 302} 303 304int 305md_pre_mount(struct install_partition_desc *install, size_t ndx) 306{ 307 return 0; 308} 309 310bool 311md_mbr_update_check(struct disk_partitions *parts, mbr_info_t *mbri) 312{ 313 return false; /* no change, no need to write back */ 314} 315 316#ifdef HAVE_GPT 317bool 318md_gpt_post_write(struct disk_partitions *parts, part_id root_id, 319 bool root_is_new, part_id efi_id, bool efi_is_new) 320{ 321 /* no GPT boot support, nothing needs to be done here */ 322 return true; 323} 324#endif 325