1 #include <grub/types.h>
3 #include <grub/linux.h>
28 struct grub_linux_initrd_component
43 hex (grub_uint8_t val
)
47 return 'a' + val
- 10;
51 set_field (char *var
, grub_uint32_t val
)
55 for (i
= 28; i
>= 0; i
-= 4)
56 *ptr
++ = hex((val
>> i
) & 0xf);
60 make_header (grub_uint8_t
*ptr
,
61 const char *name
, grub_size_t len
,
65 struct newc_head
*head
= (struct newc_head
*) ptr
;
68 grub_memcpy (head
->magic
, "070701", 6);
69 set_field (head
->ino
, 0);
70 set_field (head
->mode
, mode
);
71 set_field (head
->uid
, 0);
72 set_field (head
->gid
, 0);
73 set_field (head
->nlink
, 1);
74 set_field (head
->mtime
, 0);
75 set_field (head
->filesize
, fsize
);
76 set_field (head
->devmajor
, 0);
77 set_field (head
->devminor
, 0);
78 set_field (head
->rdevmajor
, 0);
79 set_field (head
->rdevminor
, 0);
80 set_field (head
->namesize
, len
);
81 set_field (head
->check
, 0);
83 ptr
+= sizeof (struct newc_head
);
84 grub_memcpy (ptr
, name
, len
);
86 oh
= ALIGN_UP_OVERHEAD (ptr
- optr
, 4);
87 grub_memset (ptr
, 0, oh
);
93 free_dir (struct dir
*root
)
97 free_dir (root
->next
);
98 free_dir (root
->child
);
99 grub_free (root
->name
);
104 insert_dir (const char *name
, struct dir
**root
,
107 struct dir
*cur
, **head
= root
;
108 const char *cb
, *ce
= name
;
109 grub_size_t size
= 0;
112 for (cb
= ce
; *cb
== '/'; cb
++);
113 for (ce
= cb
; *ce
&& *ce
!= '/'; ce
++);
117 for (cur
= *root
; cur
; cur
= cur
->next
)
118 if (grub_memcmp (cur
->name
, cb
, ce
- cb
)
119 && cur
->name
[ce
- cb
] == 0)
124 n
= grub_zalloc (sizeof (*n
));
128 n
->name
= grub_strndup (cb
, ce
- cb
);
131 grub_dprintf ("linux", "Creating directory %s, %s\n", name
, ce
);
132 ptr
= make_header (ptr
, name
, ce
- name
,
135 size
+= ALIGN_UP ((ce
- (char *) name
)
136 + sizeof (struct newc_head
), 4);
146 grub_initrd_init (int argc
, char *argv
[],
147 struct grub_linux_initrd_context
*initrd_ctx
)
151 struct dir
*root
= 0;
153 initrd_ctx
->nfiles
= 0;
154 initrd_ctx
->components
= 0;
156 initrd_ctx
->components
= grub_zalloc (argc
157 * sizeof (initrd_ctx
->components
[0]));
158 if (!initrd_ctx
->components
)
161 initrd_ctx
->size
= 0;
163 for (i
= 0; i
< argc
; i
++)
165 const char *fname
= argv
[i
];
167 initrd_ctx
->size
= ALIGN_UP (initrd_ctx
->size
, 4);
169 if (grub_memcmp (argv
[i
], "newc:", 5) == 0)
171 const char *ptr
, *eptr
;
175 eptr
= grub_strchr (ptr
, ':');
178 initrd_ctx
->components
[i
].newc_name
= grub_strndup (ptr
, eptr
- ptr
);
179 if (!initrd_ctx
->components
[i
].newc_name
)
181 grub_initrd_close (initrd_ctx
);
185 += ALIGN_UP (sizeof (struct newc_head
)
186 + grub_strlen (initrd_ctx
->components
[i
].newc_name
),
188 initrd_ctx
->size
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
196 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
197 + sizeof ("TRAILER!!!") - 1, 4);
202 initrd_ctx
->components
[i
].file
= grub_file_open (fname
,
203 GRUB_FILE_TYPE_LINUX_INITRD
204 | GRUB_FILE_TYPE_NO_DECOMPRESS
);
205 if (!initrd_ctx
->components
[i
].file
)
207 grub_initrd_close (initrd_ctx
);
210 initrd_ctx
->nfiles
++;
211 initrd_ctx
->components
[i
].size
212 = grub_file_size (initrd_ctx
->components
[i
].file
);
213 initrd_ctx
->size
+= initrd_ctx
->components
[i
].size
;
218 initrd_ctx
->size
= ALIGN_UP (initrd_ctx
->size
, 4);
219 initrd_ctx
->size
+= ALIGN_UP (sizeof (struct newc_head
)
220 + sizeof ("TRAILER!!!") - 1, 4);
225 return GRUB_ERR_NONE
;
229 grub_get_initrd_size (struct grub_linux_initrd_context
*initrd_ctx
)
231 return initrd_ctx
->size
;
235 grub_initrd_close (struct grub_linux_initrd_context
*initrd_ctx
)
238 if (!initrd_ctx
->components
)
240 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
242 grub_free (initrd_ctx
->components
[i
].newc_name
);
243 grub_file_close (initrd_ctx
->components
[i
].file
);
245 grub_free (initrd_ctx
->components
);
246 initrd_ctx
->components
= 0;
249 extern int ventoy_need_prompt_load_file(void);
250 extern grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
);
252 grub_initrd_load (struct grub_linux_initrd_context
*initrd_ctx
,
253 char *argv
[], void *target
)
255 grub_uint8_t
*ptr
= target
;
258 struct dir
*root
= 0;
259 grub_ssize_t cursize
= 0;
260 grub_ssize_t readsize
= 0;
262 for (i
= 0; i
< initrd_ctx
->nfiles
; i
++)
264 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
265 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
267 if (initrd_ctx
->components
[i
].newc_name
)
269 ptr
+= insert_dir (initrd_ctx
->components
[i
].newc_name
,
271 ptr
= make_header (ptr
, initrd_ctx
->components
[i
].newc_name
,
272 grub_strlen (initrd_ctx
->components
[i
].newc_name
),
274 initrd_ctx
->components
[i
].size
);
279 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!") - 1,
286 cursize
= initrd_ctx
->components
[i
].size
;
287 if (ventoy_need_prompt_load_file() && initrd_ctx
->components
[i
].newc_name
&&
288 grub_strcmp(initrd_ctx
->components
[i
].newc_name
, "boot.wim") == 0)
290 readsize
= ventoy_load_file_with_prompt(initrd_ctx
->components
[i
].file
, ptr
, cursize
);
294 readsize
= grub_file_read (initrd_ctx
->components
[i
].file
, ptr
, cursize
);
297 if (readsize
!= cursize
)
300 grub_error (GRUB_ERR_FILE_READ_ERROR
, N_("premature end of file %s"),
302 grub_initrd_close (initrd_ctx
);
309 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
310 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
311 ptr
= make_header (ptr
, "TRAILER!!!", sizeof ("TRAILER!!!") - 1, 0, 0);
315 return GRUB_ERR_NONE
;