ieee1275: split up grub_machine_get_bootlocation
[grub.git] / util / grub-macho2img.c
1 /* macho2img.c - tool to convert Mach-O to raw imagw.  */
2 /*
3  *  GRUB  --  GRand Unified Bootloader
4  *  Copyright (C) 2009 Free Software Foundation, Inc.
5  *
6  *  GRUB is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  GRUB is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <grub/types.h>
23 #include <grub/macho.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 /* Please don't internationalise this file. It's pointless.  */
29
30 /* XXX: this file assumes particular Mach-O layout and does no checks. */
31 /* However as build system ensures correct usage of this tool this
32    shouldn't be a problem. */
33
34 int
35 main (int argc, char **argv)
36 {
37   FILE *in, *out;
38   int do_bss = 0;
39   char *buf;
40   int bufsize;
41   struct grub_macho_header32 *head;
42   struct grub_macho_segment32 *curcmd;
43   unsigned i;
44   unsigned bssstart = 0;
45   unsigned bssend = 0;
46
47   if (argc && strcmp (argv[1], "--bss") == 0)
48     do_bss = 1;
49   if (argc < 2 + do_bss)
50     {
51       printf ("Usage: %s [--bss] filename.exec filename.img\n"
52               "Convert Mach-O into raw image\n", argv[0]);
53       return 0;
54     }
55   in = fopen (argv[1 + do_bss], "rb");
56   if (! in)
57     {
58       printf ("Couldn't open %s\n", argv[1 + do_bss]);
59       return 1;
60     }
61   out = fopen (argv[2 + do_bss], "wb");
62   if (! out)
63     {
64       fclose (in);
65       printf ("Couldn't open %s\n", argv[2 + do_bss]);
66       return 2;
67     }
68   fseek (in, 0, SEEK_END);
69   bufsize = ftell (in);
70   fseek (in, 0, SEEK_SET);
71   buf = malloc (bufsize);
72   if (! buf)
73     {
74       fclose (in);
75       fclose (out);
76       printf ("Couldn't allocate buffer\n");
77       return 3;
78     }
79   fread (buf, 1, bufsize, in);
80   head = (struct grub_macho_header32 *) buf;
81   if (grub_le_to_cpu32 (head->magic) != GRUB_MACHO_MAGIC32)
82     {
83       fclose (in);
84       fclose (out);
85       free (buf);
86       printf ("Invalid Mach-O file\n");
87       return 4;
88     }
89   curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head));
90   for (i = 0; i < grub_le_to_cpu32 (head->ncmds); i++,
91          curcmd = (struct grub_macho_segment32 *)
92          (((char *) curcmd) + curcmd->cmdsize))
93     {
94       if (curcmd->cmd != GRUB_MACHO_CMD_SEGMENT32)
95         continue;
96       fwrite (buf + grub_le_to_cpu32 (curcmd->fileoff), 1,
97               grub_le_to_cpu32 (curcmd->filesize), out);
98       if (grub_le_to_cpu32 (curcmd->vmsize)
99           > grub_le_to_cpu32 (curcmd->filesize))
100         {
101           bssstart = grub_le_to_cpu32 (curcmd->vmaddr)
102             + grub_le_to_cpu32 (curcmd->filesize) ;
103           bssend = grub_le_to_cpu32 (curcmd->vmaddr)
104             + grub_le_to_cpu32 (curcmd->vmsize) ;
105         }
106     }
107   if (do_bss)
108     {
109       grub_uint32_t tmp;
110       fseek (out, 0x5c, SEEK_SET);
111       tmp = grub_cpu_to_le32 (bssstart);
112       fwrite (&tmp, 4, 1, out);
113       tmp = grub_cpu_to_le32 (bssend);
114       fwrite (&tmp, 4, 1, out);
115     }
116   fclose (in);
117   fclose (out);
118   printf("macho2img complete\n");
119   return 0;
120 }