2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright 1993 NeXT Computer, Inc.
26 * All rights reserved.
30 #include "rcz_common.h"
31 #include "rcz_decompress_file.h"
32 #include <mach-o/fat.h>
34 static int devMajor
[3] = { 6, 3, 1 }; // sd, hd, fd major dev #'s
36 static int xread(int fd
, char * addr
, int size
);
37 static int loadmacho(struct mach_header
* head
, int dev
, int io
,
38 entry_t
* rentry
, char ** raddr
, int * rsize
,
41 //==========================================================================
42 // Open a file for reading. If the file doesn't exist,
43 // try opening the compressed version.
45 #ifdef RCZ_COMPRESSED_FILE_SUPPORT
46 int openfile(const char * filename
, int ignored
)
52 if ((fd
= open(filename
, 0)) < 0) {
54 sprintf(buf
, "%s%s", filename
, RCZ_EXTENSION
);
55 if ((fd
= open(buf
, 0)) >= 0) {
56 size
= rcz_file_size(fd
);
57 addr
= (unsigned char *)((KERNEL_ADDR
+ KERNEL_LEN
) - size
);
58 ret
= rcz_decompress_file(fd
, addr
);
63 fd
= openmem(addr
, size
);
70 int openfile(char * filename
, int ignored
)
72 return open(filename
, 0);
76 //==========================================================================
79 int loadprog( int dev
, int fd
, struct mach_header
* headOut
,
80 entry_t
* entry
, /* entry point */
81 char ** addr
, /* load address */
82 int * size
) /* size of loaded program */
84 struct mach_header head
;
90 read(fd
, (char *) &head
, sizeof(head
));
93 bcopy((char *) &head
, (char *) headOut
, sizeof(head
));
95 if ( head
.magic
== MH_MAGIC
)
97 return loadmacho(&head
, dev
, fd
, entry
, addr
, size
, file_offset
);
99 else if ( file_offset
== 0 &&
100 ((head
.magic
== FAT_CIGAM
) || (head
.magic
== FAT_MAGIC
)) )
102 int swap
= (head
.magic
== FAT_CIGAM
) ? 1 : 0;
103 struct fat_header
* fhp
= (struct fat_header
*) &head
;
104 struct fat_arch
* fap
;
105 int i
, narch
= swap
? NXSwapLong(fhp
->nfat_arch
) : fhp
->nfat_arch
;
109 size
= sizeof(struct fat_arch
) * narch
;
114 for ( i
= 0, fap
= (struct fat_arch
*)(buf
+sizeof(struct fat_header
));
118 cpu
= swap
? NXSwapLong(fap
->cputype
) : fap
->cputype
;
119 if (cpu
== CPU_TYPE_I386
)
121 /* that's specific enough */
123 file_offset
= swap
? NXSwapLong(fap
->offset
) : fap
->offset
;
124 b_lseek(fd
, file_offset
, 0);
129 error("Fat binary file doesn't contain i386 code\n");
132 error("Unrecognized binary format: %08x\n", head
.magic
);
136 //==========================================================================
139 // Read from file descriptor. addr is a physical address.
141 static int xread( int fd
, char * addr
, int size
)
143 char * orgaddr
= addr
;
149 int bufsize
= BUFSIZ
;
152 printf("xread: addr=%x, size=%x\n", addr
, size
);
156 buf
= malloc(BUFSIZ
);
158 // align your read to increase speed
159 offset
= tell(fd
) & 4095;
167 if ( size
> max
) count
= max
;
170 printf("xread: loop size=%x, count=%x\n", size
, count
);
174 if ( read(fd
, buf
, count
) != count
) break;
176 bcopy(buf
, ptov(addr
), count
);
184 if ( tick
> (50*1024) )
196 //==========================================================================
199 static int loadmacho( struct mach_header
* head
, int dev
, int io
,
200 entry_t
* rentry
, char ** raddr
, int * rsize
,
206 unsigned int entry
= 0;
208 unsigned int vmaddr
= ~0;
209 unsigned int vmend
= 0;
211 struct xxx_thread_command
{
213 unsigned long cmdsize
;
214 unsigned long flavor
;
216 i386_thread_state_t state
;
219 // XXX should check cputype
220 cmds
= malloc(head
->sizeofcmds
);
221 b_lseek(io
, sizeof(struct mach_header
) + file_offset
, 0);
223 if ( read(io
, (char *) cmds
, head
->sizeofcmds
) != head
->sizeofcmds
)
225 error("loadmacho: error reading commands\n");
229 for ( ncmds
= head
->ncmds
, cp
= cmds
; ncmds
> 0; ncmds
-- )
233 #define lcp ((struct load_command *) cp)
234 #define scp ((struct segment_command *) cp)
239 addr
= (scp
->vmaddr
& 0x3fffffff) + (int)*raddr
;
242 vmsize
+= scp
->vmsize
;
243 vmaddr
= min(vmaddr
, addr
);
244 vmend
= max(vmend
, addr
+ scp
->vmsize
);
246 // Zero any space at the end of the segment.
248 bzero((char *)(addr
+ scp
->filesize
),
249 scp
->vmsize
- scp
->filesize
);
251 // FIXME: check to see if we overflow
252 // the available space (should be passed in
253 // as the size argument).
256 printf("LC: fileoff %x, filesize %x, off %x, addr %x\n",
257 scp
->fileoff
, scp
->filesize
, file_offset
, addr
);
261 b_lseek(io
, scp
->fileoff
+ file_offset
, 0);
262 if ( xread(io
, (char *)addr
, scp
->filesize
)
265 error("loadmacho: error loading section\n");
273 th
= (struct xxx_thread_command
*) cp
;
274 entry
= th
->state
.eip
;
280 kernBootStruct
->rootdev
= (dev
& 0xffffff00) | devMajor
[B_TYPE(dev
)];
284 *rentry
= (entry_t
)( (int) entry
& 0x3fffffff );
285 *rsize
= vmend
- vmaddr
;
286 *raddr
= (char *)vmaddr
;