1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* -*- linux-c -*- --------------------------- 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * Copyright 2007 rPath, Inc. - All Rights R 6 * Copyright 2009 Intel Corporation; author 7 * 8 * ------------------------------------------- 9 10 /* 11 * Get EDD BIOS disk information 12 */ 13 14 #include "boot.h" 15 #include <linux/edd.h> 16 #include "string.h" 17 18 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_ 19 20 /* 21 * Read the MBR (first sector) from a specific 22 */ 23 static int read_mbr(u8 devno, void *buf) 24 { 25 struct biosregs ireg, oreg; 26 27 initregs(&ireg); 28 ireg.ax = 0x0201; /* Leg 29 ireg.cx = 0x0001; /* Sec 30 ireg.dl = devno; 31 ireg.bx = (size_t)buf; 32 33 intcall(0x13, &ireg, &oreg); 34 35 return -(oreg.eflags & X86_EFLAGS_CF); 36 } 37 38 static u32 read_mbr_sig(u8 devno, struct edd_i 39 { 40 int sector_size; 41 char *mbrbuf_ptr, *mbrbuf_end; 42 u32 buf_base, mbr_base; 43 extern char _end[]; 44 u16 mbr_magic; 45 46 sector_size = ei->params.bytes_per_sec 47 if (!sector_size) 48 sector_size = 512; /* Best ava 49 50 /* Produce a naturally aligned buffer 51 buf_base = (ds() << 4) + (u32)&_end; 52 mbr_base = (buf_base+sector_size-1) & 53 mbrbuf_ptr = _end + (mbr_base-buf_base 54 mbrbuf_end = mbrbuf_ptr + sector_size; 55 56 /* Make sure we actually have space on 57 if (!(boot_params.hdr.loadflags & CAN_ 58 return -1; 59 if (mbrbuf_end > (char *)(size_t)boot_ 60 return -1; 61 62 memset(mbrbuf_ptr, 0, sector_size); 63 if (read_mbr(devno, mbrbuf_ptr)) 64 return -1; 65 66 *mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_ 67 mbr_magic = *(u16 *)&mbrbuf_ptr[510]; 68 69 /* check for valid MBR magic */ 70 return mbr_magic == 0xAA55 ? 0 : -1; 71 } 72 73 static int get_edd_info(u8 devno, struct edd_i 74 { 75 struct biosregs ireg, oreg; 76 77 memset(ei, 0, sizeof(*ei)); 78 79 /* Check Extensions Present */ 80 81 initregs(&ireg); 82 ireg.ah = 0x41; 83 ireg.bx = EDDMAGIC1; 84 ireg.dl = devno; 85 intcall(0x13, &ireg, &oreg); 86 87 if (oreg.eflags & X86_EFLAGS_CF) 88 return -1; /* No extended 89 90 if (oreg.bx != EDDMAGIC2) 91 return -1; 92 93 ei->device = devno; 94 ei->version = oreg.ah; /* ED 95 ei->interface_support = oreg.cx; /* ED 96 97 /* Extended Get Device Parameters */ 98 99 ei->params.length = sizeof(ei->params) 100 ireg.ah = 0x48; 101 ireg.si = (size_t)&ei->params; 102 intcall(0x13, &ireg, &oreg); 103 104 /* Get legacy CHS parameters */ 105 106 /* Ralf Brown recommends setting ES:DI 107 ireg.ah = 0x08; 108 ireg.es = 0; 109 intcall(0x13, &ireg, &oreg); 110 111 if (!(oreg.eflags & X86_EFLAGS_CF)) { 112 ei->legacy_max_cylinder = oreg 113 ei->legacy_max_head = oreg.dh; 114 ei->legacy_sectors_per_track = 115 } 116 117 return 0; 118 } 119 120 void query_edd(void) 121 { 122 char eddarg[8]; 123 int do_mbr = 1; 124 #ifdef CONFIG_EDD_OFF 125 int do_edd = 0; 126 #else 127 int do_edd = 1; 128 #endif 129 int be_quiet; 130 int devno; 131 struct edd_info ei, *edp; 132 u32 *mbrptr; 133 134 if (cmdline_find_option("edd", eddarg, 135 if (!strcmp(eddarg, "skipmbr") 136 do_edd = 1; 137 do_mbr = 0; 138 } 139 else if (!strcmp(eddarg, "off" 140 do_edd = 0; 141 else if (!strcmp(eddarg, "on") 142 do_edd = 1; 143 } 144 145 be_quiet = cmdline_find_option_bool("q 146 147 edp = boot_params.eddbuf; 148 mbrptr = boot_params.edd_mbr_sig_buffe 149 150 if (!do_edd) 151 return; 152 153 /* Bugs in OnBoard or AddOnCards Bios 154 * so give a hint if this happens. 155 */ 156 157 if (!be_quiet) 158 printf("Probing EDD (edd=off t 159 160 for (devno = 0x80; devno < 0x80+EDD_MB 161 /* 162 * Scan the BIOS-supported har 163 * information... 164 */ 165 if (!get_edd_info(devno, &ei) 166 && boot_params.eddbuf_entr 167 memcpy(edp, &ei, sizeo 168 edp++; 169 boot_params.eddbuf_ent 170 } 171 172 if (do_mbr && !read_mbr_sig(de 173 boot_params.edd_mbr_si 174 } 175 176 if (!be_quiet) 177 printf("ok\n"); 178 } 179 180 #endif 181
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.