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.
31 #include "kernBootStruct.h"
32 #include "rcz_common.h"
33 #include <ufs/ufs/dir.h>
34 #include <mach-o/fat.h>
36 static int devMajor
[3] = { 6, 3, 1 }; // sd, hd, fd major dev #'s
38 //==========================================================================
39 // Open a file for reading. If the file doesn't exist,
40 // try opening the compressed version.
42 #ifdef RCZ_COMPRESSED_FILE_SUPPORT
44 openfile(char *filename
, int ignored
)
50 if ((fd
= open(filename
, 0)) < 0) {
52 sprintf(buf
, "%s%s", filename
, RCZ_EXTENSION
);
53 if ((fd
= open(buf
, 0)) >= 0) {
54 size
= rcz_file_size(fd
);
55 addr
= (unsigned char *)((KERNEL_ADDR
+ KERNEL_LEN
) - size
);
56 ret
= rcz_decompress_file(fd
, addr
);
61 fd
= openmem(addr
, size
);
69 openfile(char *filename
, int ignored
)
71 return open(filename
, 0);
75 //==========================================================================
81 struct mach_header
* headOut
,
82 entry_t
* entry
, /* entry point */
83 char ** addr
, /* load address */
84 int * size
) /* size of loaded program */
86 struct mach_header head
;
92 read(fd
, (char *) &head
, sizeof(head
));
95 bcopy((char *) &head
, (char *) headOut
, sizeof(head
));
97 if ( head
.magic
== MH_MAGIC
)
99 return loadmacho(&head
, dev
, fd
, entry
, addr
, size
, file_offset
);
101 else if ( file_offset
== 0 &&
102 ((head
.magic
== FAT_CIGAM
) || (head
.magic
== FAT_MAGIC
)) )
104 int swap
= (head
.magic
== FAT_CIGAM
) ? 1 : 0;
105 struct fat_header
* fhp
= (struct fat_header
*) &head
;
106 struct fat_arch
* fap
;
107 int i
, narch
= swap
? NXSwapLong(fhp
->nfat_arch
) : fhp
->nfat_arch
;
111 size
= sizeof(struct fat_arch
) * narch
;
116 for ( i
= 0, fap
= (struct fat_arch
*)(buf
+sizeof(struct fat_header
));
120 cpu
= swap
? NXSwapLong(fap
->cputype
) : fap
->cputype
;
121 if (cpu
== CPU_TYPE_I386
)
123 /* that's specific enough */
125 file_offset
= swap
? NXSwapLong(fap
->offset
) : fap
->offset
;
126 b_lseek(fd
, file_offset
, 0);
131 error("Fat binary file doesn't contain i386 code\n");
134 error("Unrecognized binary format: %08x\n", head
.magic
);
138 //==========================================================================
141 // Read from file descriptor. addr is a physical address.
147 char * orgaddr
= addr
;
153 int bufsize
= BUFSIZ
;
156 printf("xread: addr=%x, size=%x\n", addr
, size
);
160 buf
= malloc(BUFSIZ
);
162 // align your read to increase speed
163 offset
= tell(fd
) & 4095;
171 if ( size
> max
) count
= max
;
174 printf("xread: loop size=%x, count=%x\n", size
, count
);
178 if ( read(fd
, buf
, count
) != count
) break;
180 bcopy(buf
, ptov(addr
), count
);
188 if ( tick
> (50*1024) )
200 //==========================================================================
204 loadmacho( struct mach_header
* head
,
215 unsigned int entry
= 0;
217 unsigned int vmaddr
= ~0;
218 unsigned int vmend
= 0;
220 struct xxx_thread_command
{
222 unsigned long cmdsize
;
223 unsigned long flavor
;
225 i386_thread_state_t state
;
228 // XXX should check cputype
229 cmds
= malloc(head
->sizeofcmds
);
230 b_lseek(io
, sizeof(struct mach_header
) + file_offset
, 0);
232 if ( read(io
, (char *) cmds
, head
->sizeofcmds
) != head
->sizeofcmds
)
234 error("loadmacho: error reading commands\n");
238 for ( ncmds
= head
->ncmds
, cp
= cmds
; ncmds
> 0; ncmds
-- )
242 #define lcp ((struct load_command *) cp)
243 #define scp ((struct segment_command *) cp)
248 addr
= (scp
->vmaddr
& 0x3fffffff) + (int)*raddr
;
251 vmsize
+= scp
->vmsize
;
252 vmaddr
= min(vmaddr
, addr
);
253 vmend
= max(vmend
, addr
+ scp
->vmsize
);
255 // Zero any space at the end of the segment.
257 bzero((char *)(addr
+ scp
->filesize
),
258 scp
->vmsize
- scp
->filesize
);
260 // FIXME: check to see if we overflow
261 // the available space (should be passed in
262 // as the size argument).
265 printf("LC: fileoff %x, filesize %x, off %x, addr %x\n",
266 scp
->fileoff
, scp
->filesize
, file_offset
, addr
);
270 b_lseek(io
, scp
->fileoff
+ file_offset
, 0);
271 if ( xread(io
, (char *)addr
, scp
->filesize
)
274 error("loadmacho: error loading section\n");
282 th
= (struct xxx_thread_command
*) cp
;
283 entry
= th
->state
.eip
;
289 kernBootStruct
->rootdev
= (dev
& 0xffffff00) | devMajor
[Dev(dev
)];
293 *rentry
= (entry_t
)( (int) entry
& 0x3fffffff );
294 *rsize
= vmend
- vmaddr
;
295 *raddr
= (char *)vmaddr
;