1 #include <grub/types.h>
3 #include <grub/linux.h>
26 struct grub_linux_initrd_component
41 hex (grub_uint8_t val
)
45 return 'a' + val
- 10;
49 set_field (char *var
, grub_uint32_t val
)
53 for (i
= 28; i
>= 0; i
-= 4)
54 *ptr
++ = hex((val
>> i
) & 0xf);
58 make_header (grub_uint8_t
*ptr
,
59 const char *name
, grub_size_t len
,
63 struct newc_head
*head
= (struct newc_head
*) ptr
;
66 grub_memcpy (head
->magic
, "070701", 6);
67 set_field (head
->ino
, 0);
68 set_field (head
->mode
, mode
);
69 set_field (head
->uid
, 0);
70 set_field (head
->gid
, 0);
71 set_field (head
->nlink
, 1);
72 set_field (head
->mtime
, 0);
73 set_field (head
->filesize
, fsize
);
74 set_field (head
->devmajor
, 0);
75 set_field (head
->devminor
, 0);
76 set_field (head
->rdevmajor
, 0);
77 set_field (head
->rdevminor
, 0);
78 set_field (head
->namesize
, len
);
79 set_field (head
->check
, 0);
81 ptr
+= sizeof (struct newc_head
);
82 grub_memcpy (ptr
, name
, len
);
84 oh
= ALIGN_UP_OVERHEAD (ptr
- optr
, 4);
85 grub_memset (ptr
, 0, oh
);
91 free_dir (struct dir
*root
)
95 free_dir (root
->next
);
96 free_dir (root
->child
);
97 grub_free (root
->name
);
102 insert_dir (const char *name
, struct dir
**root
,
105 struct dir
*cur
, **head
= root
;
106 const char *cb
, *ce
= name
;
107 grub_size_t size
= 0;
110 for (cb
= ce
; *cb
== '/'; cb
++);
111 for (ce
= cb
; *ce
&& *ce
!= '/'; ce
++);
115 for (cur
= *root
; cur
; cur
= cur
->next
)
116 if (grub_memcmp (cur
->name
, cb
, ce
- cb
)
117 && cur
->name
[ce
- cb
] == 0)
122 n
= grub_zalloc (sizeof (*n
));
126 n
->name
= grub_strndup (cb
, ce
- cb
);
129 grub_dprintf ("linux", "Creating directory %s, %s\n", name
, ce
);
130 ptr
= make_header (ptr
, name
, ce
- name
,
133 size
+= ALIGN_UP ((ce
- (char *) name
)
134 + sizeof (struct newc_head
), 4);
144 grub_initrd_init (int argc
, char *argv
[],
145 struct grub_linux_initrd_context
*initrd_ctx
)
149 struct dir
*root
= 0;
151 initrd_ctx
->nfiles
= 0;
152 initrd_ctx
->components
= 0;
154 initrd_ctx
->components
= grub_zalloc (argc
155 * sizeof (initrd_ctx
->components
[0]));
156 if (!initrd_ctx
->components
)
159 initrd_ctx
->size
= 0;
161 for (i
= 0; i
< argc
; i
++)
163 const char *fname
= argv
[i
];
164 if (grub_memcmp (argv
[i
], "newc:", 5) == 0)
166 const char *ptr
, *eptr
;
170 eptr
= grub_strchr (ptr
, ':');
173 grub_file_filter_disable_compression ();
174 initrd_ctx
->components
[i
].newc_name
= grub_strndup (ptr
, eptr
- ptr
);
175 if (!initrd_ctx
->components
[i
].newc_name
)
177 grub_initrd_close (initrd_ctx
);
181 += ALIGN_UP (sizeof (struct newc_head
)
182 + grub_strlen (initrd_ctx
->components
[i
].newc_name
),
184 initrd_ctx
->size
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
192 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
193 + sizeof ("TRAILER!!!") - 1, 4);
198 grub_file_filter_disable_compression ();
199 initrd_ctx
->components
[i
].file
= grub_file_open (fname
);
200 if (!initrd_ctx
->components
[i
].file
)
202 grub_initrd_close (initrd_ctx
);
205 initrd_ctx
->nfiles
++;
206 initrd_ctx
->components
[i
].size
207 = grub_file_size (initrd_ctx
->components
[i
].file
);
208 initrd_ctx
->size
+= ALIGN_UP (initrd_ctx
->components
[i
].size
, 4);
213 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
214 + sizeof ("TRAILER!!!") - 1, 4);
219 return GRUB_ERR_NONE
;
223 grub_get_initrd_size (struct grub_linux_initrd_context
*initrd_ctx
)
225 return initrd_ctx
->size
;
229 grub_initrd_close (struct grub_linux_initrd_context
*initrd_ctx
)
232 if (!initrd_ctx
->components
)
234 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
236 grub_free (initrd_ctx
->components
[i
].newc_name
);
237 grub_file_close (initrd_ctx
->components
[i
].file
);
239 grub_free (initrd_ctx
->components
);
240 initrd_ctx
->components
= 0;
244 grub_initrd_load (struct grub_linux_initrd_context
*initrd_ctx
,
245 char *argv
[], void *target
)
247 grub_uint8_t
*ptr
= target
;
250 struct dir
*root
= 0;
252 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
254 grub_ssize_t cursize
;
256 if (initrd_ctx
->components
[i
].newc_name
)
258 ptr
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
260 ptr
= make_header (ptr
, initrd_ctx
->components
[i
].newc_name
,
261 grub_strlen (initrd_ctx
->components
[i
].newc_name
),
263 initrd_ctx
->components
[i
].size
);
268 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!") - 1,
275 cursize
= initrd_ctx
->components
[i
].size
;
276 if (grub_file_read (initrd_ctx
->components
[i
].file
, ptr
, cursize
)
280 grub_error (GRUB_ERR_FILE_READ_ERROR
, N_("premature end of file %s"),
282 grub_initrd_close (initrd_ctx
);
286 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
287 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
290 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
293 return GRUB_ERR_NONE
;