6 #define min(a,b) (((a) < (b)) ? (a) : (b))
9 SUFFIX (grub_macho_contains_macho
) (grub_macho_t macho
)
11 return macho
->offsetXX
!= -1;
15 SUFFIX (grub_macho_parse
) (grub_macho_t macho
)
17 grub_macho_header_t head
;
19 /* Is there any candidate at all? */
20 if (macho
->offsetXX
== -1)
23 /* Read header and check magic*/
24 if (grub_file_seek (macho
->file
, macho
->offsetXX
) == (grub_off_t
) -1
25 || grub_file_read (macho
->file
, &head
, sizeof (head
))
28 grub_error (GRUB_ERR_READ_ERROR
, "cannot read Mach-O header");
32 if (head
.magic
!= GRUB_MACHO_MAGIC
)
34 grub_error (GRUB_ERR_BAD_OS
, "invalid Mach-O " XX
"-bit header");
40 macho
->ncmdsXX
= head
.ncmds
;
41 macho
->cmdsizeXX
= head
.sizeofcmds
;
42 macho
->cmdsXX
= grub_malloc(macho
->cmdsizeXX
);
45 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "not enough memory to read commands");
48 if (grub_file_read (macho
->file
, macho
->cmdsXX
,
49 (grub_size_t
) macho
->cmdsizeXX
)
50 != (grub_ssize_t
) macho
->cmdsizeXX
)
52 grub_error (GRUB_ERR_READ_ERROR
, "cannot read Mach-O header");
57 typedef int NESTED_FUNC_ATTR (*grub_macho_iter_hook_t
)
58 (grub_macho_t
, struct grub_macho_cmd
*,
62 grub_macho_cmds_iterate (grub_macho_t macho
,
63 grub_macho_iter_hook_t hook
,
66 grub_uint8_t
*hdrs
= macho
->cmdsXX
;
69 return grub_error (GRUB_ERR_BAD_OS
, "couldn't find " XX
"-bit Mach-O");
70 for (i
= 0; i
< macho
->ncmdsXX
; i
++)
72 struct grub_macho_cmd
*hdr
= (struct grub_macho_cmd
*) hdrs
;
73 if (hook (macho
, hdr
, hook_arg
))
82 SUFFIX (grub_macho_filesize
) (grub_macho_t macho
)
84 if (SUFFIX (grub_macho_contains_macho
) (macho
))
85 return macho
->endXX
- macho
->offsetXX
;
90 SUFFIX (grub_macho_readfile
) (grub_macho_t macho
, void *dest
)
93 if (! SUFFIX (grub_macho_contains_macho
) (macho
))
94 return grub_error (GRUB_ERR_BAD_OS
,
95 "couldn't read architecture-specific part");
97 if (grub_file_seek (macho
->file
, macho
->offsetXX
) == (grub_off_t
) -1)
100 return grub_error (GRUB_ERR_BAD_OS
,
101 "invalid offset in program header");
104 read
= grub_file_read (macho
->file
, dest
,
105 macho
->endXX
- macho
->offsetXX
);
106 if (read
!= (grub_ssize_t
) (macho
->endXX
- macho
->offsetXX
))
109 return grub_error (GRUB_ERR_BAD_OS
,
110 "couldn't read architecture-specific part");
112 return GRUB_ERR_NONE
;
115 /* Calculate the amount of memory spanned by the segments. */
117 SUFFIX (grub_macho_size
) (grub_macho_t macho
, grub_macho_addr_t
*segments_start
,
118 grub_macho_addr_t
*segments_end
, int flags
)
122 /* Run through the program headers to calculate the total memory size we
124 auto int NESTED_FUNC_ATTR
calcsize (grub_macho_t _macho
,
125 struct grub_macho_cmd
*phdr
, void *_arg
);
126 int NESTED_FUNC_ATTR
calcsize (grub_macho_t _macho
__attribute__ ((unused
)),
127 struct grub_macho_cmd
*hdr0
,
128 void *_arg
__attribute__ ((unused
)))
130 grub_macho_segment_t
*hdr
= (grub_macho_segment_t
*) hdr0
;
131 if (hdr
->cmd
!= GRUB_MACHO_CMD_SEGMENT
)
137 if (! hdr
->filesize
&& (flags
& GRUB_MACHO_NOBSS
))
141 if (hdr
->vmaddr
< *segments_start
)
142 *segments_start
= hdr
->vmaddr
;
143 if (hdr
->vmaddr
+ hdr
->vmsize
> *segments_end
)
144 *segments_end
= hdr
->vmaddr
+ hdr
->vmsize
;
148 *segments_start
= (grub_macho_addr_t
) -1;
151 grub_macho_cmds_iterate (macho
, calcsize
, 0);
154 return grub_error (GRUB_ERR_BAD_OS
, "no program headers present");
156 if (*segments_end
< *segments_start
)
157 /* Very bad addresses. */
158 return grub_error (GRUB_ERR_BAD_OS
, "bad program header load addresses");
160 return GRUB_ERR_NONE
;
163 /* Load every loadable segment into memory specified by `_load_hook'. */
165 SUFFIX (grub_macho_load
) (grub_macho_t macho
, char *offset
, int flags
)
168 auto int NESTED_FUNC_ATTR
do_load(grub_macho_t _macho
,
169 struct grub_macho_cmd
*hdr0
,
170 void *_arg
__attribute__ ((unused
)));
171 int NESTED_FUNC_ATTR
do_load(grub_macho_t _macho
,
172 struct grub_macho_cmd
*hdr0
,
173 void *_arg
__attribute__ ((unused
)))
175 grub_macho_segment_t
*hdr
= (grub_macho_segment_t
*) hdr0
;
177 if (hdr
->cmd
!= GRUB_MACHO_CMD_SEGMENT
)
180 if (! hdr
->filesize
&& (flags
& GRUB_MACHO_NOBSS
))
185 if (grub_file_seek (_macho
->file
, hdr
->fileoff
186 + _macho
->offsetXX
) == (grub_off_t
) -1)
189 grub_error (GRUB_ERR_BAD_OS
,
190 "invalid offset in program header");
197 read
= grub_file_read (_macho
->file
, offset
+ hdr
->vmaddr
,
198 min (hdr
->filesize
, hdr
->vmsize
));
199 if (read
!= (grub_ssize_t
) min (hdr
->filesize
, hdr
->vmsize
))
201 /* XXX How can we free memory from `load_hook'? */
203 err
=grub_error (GRUB_ERR_BAD_OS
,
204 "couldn't read segment from file: "
205 "wanted 0x%lx bytes; read 0x%lx bytes",
206 hdr
->filesize
, read
);
211 if (hdr
->filesize
< hdr
->vmsize
)
212 grub_memset (offset
+ hdr
->vmaddr
+ hdr
->filesize
,
213 0, hdr
->vmsize
- hdr
->filesize
);
217 grub_macho_cmds_iterate (macho
, do_load
, 0);
223 SUFFIX (grub_macho_get_entry_point
) (grub_macho_t macho
)
225 grub_macho_addr_t entry_point
= 0;
226 auto int NESTED_FUNC_ATTR
hook(grub_macho_t _macho
,
227 struct grub_macho_cmd
*hdr
,
228 void *_arg
__attribute__ ((unused
)));
229 int NESTED_FUNC_ATTR
hook(grub_macho_t _macho
__attribute__ ((unused
)),
230 struct grub_macho_cmd
*hdr
,
231 void *_arg
__attribute__ ((unused
)))
233 if (hdr
->cmd
== GRUB_MACHO_CMD_THREAD
)
234 entry_point
= ((grub_macho_thread_t
*) hdr
)->entry_point
;
237 grub_macho_cmds_iterate (macho
, hook
, 0);