2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * The contents of this file constitute Original Code as defined in and 
   7  * are subject to the Apple Public Source License Version 1.1 (the 
   8  * "License").  You may not use this file except in compliance with the 
   9  * License.  Please obtain a copy of the License at 
  10  * http://www.apple.com/publicsource and read it before using this file. 
  12  * This Original Code and all software distributed under the License are 
  13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the 
  17  * License for the specific language governing rights and limitations 
  20  * @APPLE_LICENSE_HEADER_END@ 
  22 /* Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
  24  *      File:   kern/mach_fat.c 
  27  *      Fat file support routines. 
  31 #include <sys/param.h> 
  32 #include <sys/types.h> 
  34 #include <sys/vnode.h> 
  35 #include <vm/vm_kern.h> 
  36 #include <mach/kern_return.h> 
  37 #include <mach/vm_param.h> 
  38 #include <kern/cpu_number.h> 
  39 #include <mach-o/fat.h> 
  40 #include <kern/mach_loader.h> 
  41 #include <architecture/byte_order.h> 
  43 /* XXX should be in common header */ 
  44 extern int grade_binary(cpu_type_t exectype
, cpu_subtype_t execsubtype
); 
  46 #define CPU_TYPE_NATIVE         (cpu_type()) 
  47 #define CPU_TYPE_CLASSIC        CPU_TYPE_POWERPC 
  49 /********************************************************************** 
  50  * Routine:     fatfile_getarch2() 
  52  * Function:    Locate the architecture-dependant contents of a fat 
  53  *              file that match this CPU. 
  55  * Args:        vp:             The vnode for the fat file. 
  56  *              header:         A pointer to the fat file header. 
  57  *              req_cpu_type:   The required cpu type. 
  58  *              mask_bits:      Bits to mask from the sub-image type when 
  59  *                              grading it vs. the req_cpu_type 
  60  *              archret (out):  Pointer to fat_arch structure to hold 
  63  * Returns:     KERN_SUCCESS:   Valid architecture found. 
  64  *              KERN_FAILURE:   No valid architecture found. 
  65  **********************************************************************/ 
  71         __unused 
struct vnode   
*vp
, 
  74         cpu_type_t      req_cpu_type
, 
  76         struct fat_arch 
*archret
) 
  78         /* vm_pager_t           pager; */ 
  82         struct fat_arch         
*arch
; 
  83         struct fat_arch         
*best_arch
; 
  88         struct fat_header       
*header
; 
  94          *      Get the pager for the file. 
  97         header 
= (struct fat_header 
*)data_ptr
; 
 100          *      Map portion that must be accessible directly into 
 103         nfat_arch 
= NXSwapBigLongToHost(header
->nfat_arch
); 
 105         end_of_archs 
= (off_t
)nfat_arch 
* sizeof(struct fat_arch
) +  
 106                 sizeof(struct fat_header
); 
 108         filesize 
= ubc_getsize(vp
); 
 109         if (end_of_archs 
> (int)filesize
) { 
 110                 return(LOAD_BADMACHO
); 
 115          * This check is limited on the top end because we are reading 
 116          * only PAGE_SIZE bytes 
 118         if (end_of_archs 
> PAGE_SIZE 
|| 
 119                 end_of_archs 
< (sizeof(struct fat_header
)+sizeof(struct fat_arch
))) 
 120                 return(LOAD_BADMACHO
); 
 122          *      Round size of fat_arch structures up to page boundry. 
 124         size 
= round_page_32(end_of_archs
); 
 126                 return(LOAD_BADMACHO
); 
 129          * Scan the fat_arch's looking for the best one. 
 134         arch 
= (struct fat_arch 
*) (addr 
+ sizeof(struct fat_header
)); 
 135         for (; nfat_arch
-- > 0; arch
++) { 
 138                  *      Check to see if right cpu type. 
 140                 if(((cpu_type_t
)NXSwapBigIntToHost(arch
->cputype
) & ~mask_bits
) != req_cpu_type
) 
 144                  *      Get the grade of the cpu subtype. 
 146                 grade 
= grade_binary( 
 147                             NXSwapBigIntToHost(arch
->cputype
), 
 148                             NXSwapBigIntToHost(arch
->cpusubtype
)); 
 151                  *      Remember it if it's the best we've seen. 
 153                 if (grade 
> best_grade
) { 
 160          *      Return our results. 
 162         if (best_arch 
== NULL
) { 
 166                             NXSwapBigIntToHost(best_arch
->cputype
); 
 167                 archret
->cpusubtype     
= 
 168                             NXSwapBigIntToHost(best_arch
->cpusubtype
); 
 170                             NXSwapBigLongToHost(best_arch
->offset
); 
 172                             NXSwapBigLongToHost(best_arch
->size
); 
 174                             NXSwapBigLongToHost(best_arch
->align
); 
 180          * Free the memory we allocated and return. 
 185 extern char classichandler
[]; 
 188 fatfile_getarch_affinity( 
 190                 vm_offset_t             data_ptr
, 
 191                 struct fat_arch 
*archret
, 
 195                 int handler 
= (classichandler
[0] != 0); 
 196                 cpu_type_t primary_type
, fallback_type
; 
 198                 if (handler 
&& affinity
) { 
 199                                 primary_type 
= CPU_TYPE_CLASSIC
; 
 200                                 fallback_type 
= CPU_TYPE_NATIVE
; 
 202                                 primary_type 
= CPU_TYPE_NATIVE
; 
 203                                 fallback_type 
= CPU_TYPE_CLASSIC
; 
 206                  * Ignore the architectural bits when determining if an image 
 207                  * in a fat file should be skipped or graded. 
 209                 lret 
= fatfile_getarch2(vp
, data_ptr
, primary_type
, CPU_ARCH_MASK
, archret
); 
 210                 if ((lret 
!= 0) && handler
) { 
 211                         lret 
= fatfile_getarch2(vp
, data_ptr
, fallback_type
, 
 217 /********************************************************************** 
 218  * Routine:     fatfile_getarch() 
 220  * Function:    Locate the architecture-dependant contents of a fat 
 221  *              file that match this CPU. 
 223  * Args:        vp:             The vnode for the fat file. 
 224  *              header:         A pointer to the fat file header. 
 225  *              archret (out):  Pointer to fat_arch structure to hold 
 228  * Returns:     KERN_SUCCESS:   Valid architecture found. 
 229  *              KERN_FAILURE:   No valid architecture found. 
 230  **********************************************************************/ 
 234         vm_offset_t     data_ptr
, 
 235         struct fat_arch         
*archret
) 
 237         return fatfile_getarch2(vp
, data_ptr
, CPU_TYPE_NATIVE
, 0, archret
); 
 240 /********************************************************************** 
 241  * Routine:     fatfile_getarch_with_bits() 
 243  * Function:    Locate the architecture-dependant contents of a fat 
 244  *              file that match this CPU. 
 246  * Args:        vp:             The vnode for the fat file. 
 247  *              archbits:       Architecture specific feature bits 
 248  *              header:         A pointer to the fat file header. 
 249  *              archret (out):  Pointer to fat_arch structure to hold 
 252  * Returns:     KERN_SUCCESS:   Valid architecture found. 
 253  *              KERN_FAILURE:   No valid architecture found. 
 254  **********************************************************************/ 
 256 fatfile_getarch_with_bits( 
 259         vm_offset_t     data_ptr
, 
 260         struct fat_arch         
*archret
) 
 262         return fatfile_getarch2(vp
, data_ptr
, archbits 
| CPU_TYPE_NATIVE
, 0, archret
);