1/* 2 * Copyright (c) 1991-2005 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#include <sys/param.h> 29#include <sys/types.h> 30#include <sys/uio.h> 31#include <sys/vnode.h> 32#include <vm/vm_kern.h> 33#include <mach/kern_return.h> 34#include <mach/vm_param.h> 35#include <kern/cpu_number.h> 36#include <mach-o/fat.h> 37#include <kern/mach_loader.h> 38#include <kern/mach_fat.h> 39#include <libkern/OSByteOrder.h> 40#include <machine/exec.h> 41 42/********************************************************************** 43 * Routine: fatfile_getarch2() 44 * 45 * Function: Locate the architecture-dependant contents of a fat 46 * file that match this CPU. 47 * 48 * Args: vp: The vnode for the fat file. 49 * header: A pointer to the fat file header. 50 * req_cpu_type: The required cpu type. 51 * mask_bits: Bits to mask from the sub-image type when 52 * grading it vs. the req_cpu_type 53 * archret (out): Pointer to fat_arch structure to hold 54 * the results. 55 * 56 * Returns: KERN_SUCCESS: Valid architecture found. 57 * KERN_FAILURE: No valid architecture found. 58 **********************************************************************/ 59static load_return_t 60fatfile_getarch2( 61#if 0 62 struct vnode *vp, 63#else 64 __unused struct vnode *vp, 65#endif 66 vm_offset_t data_ptr, 67 cpu_type_t req_cpu_type, 68 cpu_type_t mask_bits, 69 struct fat_arch *archret) 70{ 71 /* vm_pager_t pager; */ 72 vm_offset_t addr; 73 vm_size_t size; 74 load_return_t lret; 75 struct fat_arch *arch; 76 struct fat_arch *best_arch; 77 int grade; 78 int best_grade; 79 int nfat_arch; 80 off_t end_of_archs; 81 cpu_type_t testtype; 82 cpu_type_t testsubtype; 83 struct fat_header *header; 84#if 0 85 off_t filesize; 86#endif 87 88 /* 89 * Get the pager for the file. 90 */ 91 92 header = (struct fat_header *)data_ptr; 93 94 /* 95 * Map portion that must be accessible directly into 96 * kernel's map. 97 */ 98 nfat_arch = OSSwapBigToHostInt32(header->nfat_arch); 99 100 end_of_archs = (off_t)nfat_arch * sizeof(struct fat_arch) + 101 sizeof(struct fat_header); 102#if 0 103 filesize = ubc_getsize(vp); 104 if (end_of_archs > (int)filesize) { 105 return(LOAD_BADMACHO); 106 } 107#endif 108 109 /* 110 * This check is limited on the top end because we are reading 111 * only PAGE_SIZE bytes 112 */ 113 if (end_of_archs > PAGE_SIZE || 114 end_of_archs < (off_t)(sizeof(struct fat_header)+sizeof(struct fat_arch))) 115 return(LOAD_BADMACHO); 116 117 /* 118 * Round size of fat_arch structures up to page boundry. 119 */ 120 size = round_page(end_of_archs); 121 if (size == 0) 122 return(LOAD_BADMACHO); 123 124 /* 125 * Ignore LIB64 flag so that binary slices with the flag set 126 * don't choke in grade_binary. 127 */ 128 mask_bits |= CPU_SUBTYPE_LIB64; 129 130 /* 131 * Scan the fat_arch's looking for the best one. */ 132 addr = data_ptr; 133 best_arch = NULL; 134 best_grade = 0; 135 arch = (struct fat_arch *) (addr + sizeof(struct fat_header)); 136 for (; nfat_arch-- > 0; arch++) { 137 138 /* 139 * Collect flags from both cputype and cpusubtype 140 */ 141 testtype = OSSwapBigToHostInt32(arch->cputype) | 142 (OSSwapBigToHostInt32(arch->cpusubtype) & 143 CPU_SUBTYPE_MASK); 144 testsubtype = OSSwapBigToHostInt32(arch->cpusubtype) 145 & ~CPU_SUBTYPE_MASK; 146 147 /* 148 * Check to see if right cpu type. 149 */ 150 if((testtype & ~mask_bits) != req_cpu_type) { 151 continue; 152 } 153 154 /* 155 * Get the grade of the cpu subtype (without feature flags) 156 */ 157 grade = grade_binary( 158 (testtype & ~CPU_SUBTYPE_LIB64), 159 testsubtype); 160 161 /* 162 * Remember it if it's the best we've seen. 163 */ 164 if (grade > best_grade) { 165 best_grade = grade; 166 best_arch = arch; 167 } 168 } 169 170 /* 171 * Return our results. 172 */ 173 if (best_arch == NULL) { 174 lret = LOAD_BADARCH; 175 } else { 176 archret->cputype = 177 OSSwapBigToHostInt32(best_arch->cputype); 178 archret->cpusubtype = 179 OSSwapBigToHostInt32(best_arch->cpusubtype); 180 archret->offset = 181 OSSwapBigToHostInt32(best_arch->offset); 182 archret->size = 183 OSSwapBigToHostInt32(best_arch->size); 184 archret->align = 185 OSSwapBigToHostInt32(best_arch->align); 186 187 lret = LOAD_SUCCESS; 188 } 189 190 /* 191 * Free the memory we allocated and return. 192 */ 193 return(lret); 194} 195 196load_return_t 197fatfile_getarch_affinity( 198 struct vnode *vp, 199 vm_offset_t data_ptr, 200 struct fat_arch *archret, 201 int affinity __unused) 202{ 203 /* 204 * Ignore all architectural bits when determining if an image 205 * in a fat file should be skipped or graded. 206 */ 207 return fatfile_getarch2(vp, data_ptr, cpu_type(), 208 CPU_ARCH_MASK, archret); 209} 210 211/********************************************************************** 212 * Routine: fatfile_getarch() 213 * 214 * Function: Locate the architecture-dependant contents of a fat 215 * file that match this CPU. 216 * 217 * Args: vp: The vnode for the fat file. 218 * header: A pointer to the fat file header. 219 * archret (out): Pointer to fat_arch structure to hold 220 * the results. 221 * 222 * Returns: KERN_SUCCESS: Valid architecture found. 223 * KERN_FAILURE: No valid architecture found. 224 **********************************************************************/ 225load_return_t 226fatfile_getarch( 227 struct vnode *vp, 228 vm_offset_t data_ptr, 229 struct fat_arch *archret) 230{ 231 return fatfile_getarch2(vp, data_ptr, cpu_type(), 232 CPU_SUBTYPE_LIB64, archret); 233} 234 235/********************************************************************** 236 * Routine: fatfile_getarch_with_bits() 237 * 238 * Function: Locate the architecture-dependant contents of a fat 239 * file that match this CPU. 240 * 241 * Args: vp: The vnode for the fat file. 242 * archbits: Architecture specific feature bits 243 * header: A pointer to the fat file header. 244 * archret (out): Pointer to fat_arch structure to hold 245 * the results. 246 * 247 * Returns: KERN_SUCCESS: Valid architecture found. 248 * KERN_FAILURE: No valid architecture found. 249 **********************************************************************/ 250load_return_t 251fatfile_getarch_with_bits( 252 struct vnode *vp, 253 integer_t archbits, 254 vm_offset_t data_ptr, 255 struct fat_arch *archret) 256{ 257 return fatfile_getarch2(vp, data_ptr, archbits | cpu_type(), 258 CPU_SUBTYPE_LIB64, archret); 259} 260 261