* Initial import of the 'r_fs' API

- Allows to mount filesystems in virtual IO
  - Only dummy ext2 plugin ATM
  - Added 'm' command in r2 to manage mountpoints,
    list directories and retrieve files
  - Bonus: hacky version of grub/fs code to use it
    as a standalone API. Plugins will use it
  - API is quite simple and limited, read-only access
This commit is contained in:
pancake 2011-01-12 00:01:06 +01:00
parent dcb1f9d9fd
commit ca432e3f04
156 changed files with 33256 additions and 19 deletions

4
TODO
View File

@ -5,6 +5,10 @@
<{include libr/TODO}>
* Add support for aout binaries?
* eprintf should be modified to log into a file
- eprintf_open() -- start log to file
- eprintf_close() -- stop log to file
/a ??? deprecated analyze code? srsly?
* Search for wide strings /Z or so?

View File

@ -9,6 +9,8 @@ Libraries can be compiled:
./configure-plugins --enable-shared --enable-dynamic
LIBR_PLUGINS environment variable is honored as another search path for plugins
Plugins can be:
- not compiled
- compiled as shared

View File

@ -7,7 +7,7 @@ PFX=${DESTDIR}${PREFIX}
# Libraries
LIBLIST=util vm socket cons line lib io lang flags bin hash config syscall cmd
LIBLIST+=reg asm anal print parse search diff bp sign th db crypto debug core
LIBLIST+=reg asm anal print parse search diff bp sign th db crypto debug core fs
# TODO : generate single library linking against the rest
#LIBSO=libr.so

View File

@ -2,7 +2,7 @@ NAME=r_core
DEPS=r_config r_cons r_line r_io r_cmd r_util r_print r_flags r_asm r_lib
DEPS+=r_debug r_hash r_bin r_lang r_io r_anal r_parse r_print r_bp
DEPS+=r_reg r_search r_syscall r_sign r_diff r_vm r_socket
DEPS+=r_reg r_search r_syscall r_sign r_diff r_vm r_socket r_fs
OBJ=core.o cmd.o file.o config.o visual.o io.o yank.o libs.o anal.o project.o gdiff.o asm.o rtr.o

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2010 */
/* radare - LGPL - Copyright 2009-2011 */
/* nibble<.ds@gmail.com> */
/* pancake<nopcode.org> */
@ -886,6 +886,7 @@ static void r_core_cmd_bp(RCore *core, const char *input) {
}
/* TODO: this should be moved to the core->yank api */
// TODO: arg must be const !!! use strdup here
static int cmd_yank_to(RCore *core, char *arg) {
ut64 src = core->offset;
ut64 len = 0;
@ -915,13 +916,101 @@ static int cmd_yank_to(RCore *core, char *arg) {
buf = (ut8*)malloc (len);
r_core_read_at (core, src, buf, len);
r_core_write_at (core, pos, buf, len);
free(buf);
free (buf);
core->offset = src;
r_core_block_read (core, 0);
return 0;
}
static int cmd_mount(void *data, const char *_input) {
char *input, *oinput, *ptr;
RList *list;
RListIter *iter;
RFSFile *file;
RFSRoot *root;
RFSPlugin *plug;
RCore *core = (RCore *)data;
input = oinput = strdup (_input);
switch (input[0]) {
case ' ':
input++;
if (input[0]==' ')
input++;
ptr = strchr (input, ' ');
if (ptr) {
*ptr = 0;
r_fs_mount (core->fs, input, ptr+1);
} else eprintf ("Usage: m ext2 /mnt");
break;
case '-':
r_fs_umount (core->fs, input+1);
break;
case '*':
eprintf ("List commands in radare format\n");
r_list_foreach (core->fs->roots, iter, root) {
r_cons_printf ("m %s 0x%"PFMT64x" %s\n", root->fs->name, root->delta, root->path);
}
break;
case '\0':
r_list_foreach (core->fs->roots, iter, root) {
r_cons_printf ("%s\t0x%"PFMT64x"\t%s\n", root->fs->name, root->delta, root->path);
}
break;
case 'l': // list of plugins
r_list_foreach (core->fs->plugins, iter, plug) {
r_cons_printf ("%s\t%s\n", plug->name, plug->desc);
}
break;
case 'd':
input++;
if (input[0]==' ')
input++;
list = r_fs_dir (core->fs, input);
if (list) {
r_list_foreach (list, iter, file) {
r_cons_printf ("%c %s\n", file->type, file->name);
}
r_list_free (list);
} else eprintf ("Cannot open '%s' directory\n", input);
break;
case 'g':
input++;
if (input[0]==' ')
input++;
file = r_fs_open (core->fs, input);
if (file) {
// XXX: dump to file or just pipe?
r_fs_read (core->fs, file, 0, file->size);
write (1, file->data, file->size);
r_fs_close (core->fs, file);
} else eprintf ("Cannot open file\n");
break;
case 'y':
eprintf ("TODO\n");
break;
case '?':
r_cons_printf (
"Usage: m[-?*dgy] [...]\n"
" m ; list all mountpoints in human readable format\n"
" m /mnt ; list all mountpoints from a given path\n"
" m* ; same as above, but in r2 commands\n"
" ml ; list filesystem plugins\n"
" m-/ ; umount given path (/)\n"
" m? ; display this help\n"
" my ; yank contents of file into clipboard\n"
" mg /foo ; get contents of file dumped to disk (XXX?)\n"
" md / ; list directory contents for path\n"
" m? ; show this help\n"
"TODO: support multiple mountpoints and RFile IO's (need io+core refactor)\n"
);
break;
}
free (oinput);
return 0;
}
static int cmd_yank(void *data, const char *input) {
RCore *core = (RCore *)data;
switch (input[0]) {
@ -4155,6 +4244,7 @@ void r_core_cmd_init(RCore *core) {
core->cmd->macro.cmd = r_core_cmd0;
r_cmd_set_data (core->cmd, core);
r_cmd_add (core->cmd, "x", "alias for px", &cmd_hexdump);
r_cmd_add (core->cmd, "mount", "mount filesystem", &cmd_mount);
r_cmd_add (core->cmd, "analysis", "analysis", &cmd_anal);
r_cmd_add (core->cmd, "flag", "get/set flags", &cmd_flag);
r_cmd_add (core->cmd, "debug", "debugger operations", &cmd_debug);

View File

@ -203,6 +203,8 @@ R_API int r_core_init(RCore *core) {
core->print = r_print_new ();
core->print->printf = (void *)r_cons_printf;
core->lang = r_lang_new ();
core->fs = r_fs_new ();
r_io_bind (core->io, &(core->fs->iob));
r_lang_define (core->lang, "RCore", "core", core);
r_lang_set_user_ptr (core->lang, core);
core->anal = r_anal_new ();

View File

@ -6,9 +6,9 @@ include ../config.mk
foo: pre ${LIBSO} ${LIBAR} plugins
include ${STATIC_ASM_PLUGINS}
include ${STATIC_FS_PLUGINS}
STATIC_OBJS=$(subst ..,p/..,$(subst fs_,p/fs_,$(STATIC_OBJ)))
OBJ=${STATIC_OBJS} fs.o code.o
OBJ=${STATIC_OBJS} fs.o file.o
pre:
@if [ ! -e libr_fs.${EXT_SO} ]; then if [ ! -e libr_fs.${EXT_AR} ]; then rm -f ${STATIC_OBJS} ; fi ; fi

29
libr/fs/file.c Normal file
View File

@ -0,0 +1,29 @@
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
#include <r_fs.h>
R_API RFSFile *r_fs_file_new (const char *path) {
RFSFile *file = R_NEW (RFSFile);
memset (file, 0, sizeof (RFSFile));
file->name = strdup (path);
return file;
}
R_API void r_fs_file_free (RFSFile *file) {
free (file->name);
free (file->data);
free (file);
}
// TODO: Use RFSRoot and pass it in the stack instead of heap? problematic with bindings
R_API RFSRoot *r_fs_root_new (const char *path, ut64 delta) {
RFSRoot *root = R_NEW (RFSRoot);
root->path = strdup (path);
root->delta = delta;
return root;
}
R_API void r_fs_root_free (RFSRoot *root) {
free (root->path);
free (root);
}

View File

@ -1,22 +1,137 @@
/* radare - LGPL - Copyright 2008-2010 pancake<nopcode.org> */
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
#include <r_fs.h>
#include "../config.h"
static RFSPlugin *fs_static_plugins[] =
{ R_FS_STATIC_PLUGINS };
/* lifecycle */
// TODO: needs much more love
R_API RFS *r_fs_new () {
int i;
RFSPlugin *static_plugin;
RFS *fs = R_NEW (RFS);
if (fs) {
fs->roots = r_list_new ();
fs->roots->free = (RListFree)r_fs_root_free;
fs->plugins = r_list_new ();
// XXX fs->roots->free = r_fs_plugin_free;
for (i=0; fs_static_plugins[i]; i++) {
static_plugin = R_NEW (RFSPlugin);
memcpy (static_plugin, fs_static_plugins[i], sizeof (RFSPlugin));
r_fs_add (fs, static_plugin);
}
}
return fs;
}
R_API void r_fs_free (RFS* fs) {
free (fs);
}
R_API RFSRoot *r_fs_mount (RFS* fs) {
R_API RFSPlugin *r_fs_plugin_get (RFS *fs, const char *name) {
RListIter *iter;
RFSPlugin *p;
r_list_foreach (fs->plugins, iter, p) {
if (!strcmp (p->name, name))
return p;
}
return NULL;
}
R_API int r_fs_umount (RFS* fs,
R_API void r_fs_free (RFS* fs) {
r_list_free (fs->plugins);
r_list_free (fs->roots);
free (fs);
}
/* plugins */
R_API void r_fs_add (RFS *fs, RFSPlugin *p) {
// find coliding plugin name
if (p) {
if (p->init)
p->init ();
}
r_list_append (fs->plugins, p);
}
R_API void r_fs_del (RFS *fs, RFSPlugin *p) {
// TODO: implement
}
/* mountpoint */
R_API RFSRoot *r_fs_mount (RFS* fs, const char *fstype, const char *path) {
RFSPlugin *p;
RFSRoot * root;
if (path[0] != '/') {
eprintf ("r_fs_mount: invalid mountpoint\n");
return NULL;
}
//r_fs
p = r_fs_plugin_get (fs, fstype);
if (p != NULL) {
root = r_fs_root_new (path, 0); // XXX hardcoded offset
root->fs = p;
r_list_append (fs->roots, root);
eprintf ("Mounted %s on %s at 0x%llx\n", fstype, path, 0LL);
} else eprintf ("r_fs_mount: Invalid filesystem type\n");
return root;
}
static inline int r_fs_match (const char *root, const char *path) {
return (!strncmp (path, root, strlen (path)));
}
R_API int r_fs_umount (RFS* fs, const char *path) {
RFSRoot *root;
RListIter *iter;
r_list_foreach (fs->roots, iter, root) {
if (r_fs_match (path, root->path)) {
r_list_delete (fs->roots, iter);
return R_TRUE;
}
}
return R_FALSE;
}
R_API RFSRoot *r_fs_root (RFS *fs, const char *path) {
RFSRoot *root;
RListIter *iter;
r_list_foreach (fs->roots, iter, root) {
if (r_fs_match (path, root->path))
return root;
}
return NULL;
}
/* filez */
R_API RFSFile *r_fs_open (RFS* fs, const char *path) {
RFSRoot *root = r_fs_root (fs, path);
if (root)
return root->fs->open (path);
return NULL;
}
R_API void r_fs_close (RFS* fs, RFSFile *file) {
if (fs && file)
file->fs->close (file);
}
R_API int r_fs_read (RFS* fs, RFSFile *file, ut64 addr, int len) {
if (fs && file) {
free (file->data);
file->data = malloc (file->size);
file->fs->read (file, addr, len);
}
return R_FALSE;
}
R_API RList *r_fs_dir(RFS* fs, const char *path) {
if (fs) {
RFSRoot *root = r_fs_root (fs, path);
if (root)
return root->fs->dir (root, path);
eprintf ("r_fs_dir: error, path %s is not mounted\n", path);
}
return NULL;
}

29
libr/fs/p/Makefile Normal file
View File

@ -0,0 +1,29 @@
include ../../config.mk
CFLAGS+=-I../../include -Wall -shared -fPIC ${LDFLAGS_LIB} ${LDFLAGS_LINKPATH}..
# XXX
CFLAGS+=-DLIL_ENDIAN=1
CFLAGS+=-L../../util -lr_util
LDFLAGS+=${LINK}
foo: all
ALL_TARGETS=
# TODO: rename to enabled plugins
FSS=ext2.mk
include $(FSS)
all: grublib ${ALL_TARGETS}
@true
grublib:
cd grub && ${MAKE} lib
clean:
-rm -f *.${EXT_SO} *.o ${STATIC_OBJ}
cd grub && ${MAKE} clean
mrproper: clean
-rm -f *.d ../arch/*/*/*.d
.PHONY: all clean foo mrproper

9
libr/fs/p/ext2.mk Normal file
View File

@ -0,0 +1,9 @@
OBJ_EXT2=fs_ext2.o
STATIC_OBJ+=${OBJ_EXT2}
TARGET_EXT2=fs_ext2.${EXT_SO}
ALL_TARGETS+=${TARGET_EXT2}
${TARGET_EXT2}: ${OBJ_EXT2}
${CC} ${LDFLAGS} ${CFLAGS} -o ${TARGET_EXT2} ${OBJ_EXT2}

27
libr/fs/p/fs_ext2.c Normal file
View File

@ -0,0 +1,27 @@
/* radare - LGPL - Copyright 2010 pancake<nopcode.org> */
#include <r_fs.h>
static RFSFile* ext2_open(const char *path) {
return NULL;
}
static boolt ext2_read(RFSFile *fs, ut64 addr, int len) {
return R_FALSE;
}
static void ext2_close(RFSFile *fs) {
}
static RList *ext2_dir(RFSRoot *root, const char *path) {
return NULL;
}
struct r_fs_plugin_t r_fs_plugin_ext2 = {
.name = "ext2",
.desc = "ext2 filesystem",
.open = ext2_open,
.read = ext2_read,
.close = ext2_close,
.dir = ext2_dir
};

27
libr/fs/p/fs_ext2.d Normal file
View File

@ -0,0 +1,27 @@
p/fs_ext2.o: p/fs_ext2.c ../include/r_fs.h ../include/r_types.h \
../include/r_userconf.h ../include/r_types_base.h /usr/include/stdio.h \
/usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
/usr/include/gnu/stubs-32.h \
/usr/lib/gcc/i686-pc-linux-gnu/4.5.2/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i686-pc-linux-gnu/4.5.2/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
/usr/include/string.h /usr/include/xlocale.h /usr/include/stdlib.h \
/usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
/usr/include/endian.h /usr/include/bits/endian.h \
/usr/include/bits/byteswap.h /usr/include/sys/types.h \
/usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
/usr/include/bits/sigset.h /usr/include/bits/time.h \
/usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
/usr/include/alloca.h /usr/include/sys/time.h /usr/include/sys/stat.h \
/usr/include/bits/stat.h /usr/include/fcntl.h /usr/include/bits/fcntl.h \
/usr/include/bits/uio.h /usr/include/dirent.h /usr/include/bits/dirent.h \
/usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h \
/usr/include/linux/limits.h /usr/include/unistd.h \
/usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
/usr/include/bits/confname.h /usr/include/getopt.h ../include/r_list.h \
../include/r_flist.h ../include/r_io.h ../include/r_util.h \
../include/btree.h ../include/r_types.h ../include/list.h \
/usr/include/gmp.h

31
libr/fs/p/grub/Makefile Normal file
View File

@ -0,0 +1,31 @@
# TODO include ..config.mk
CC?=gcc
KERNFILES=kern/file.c
KERNFILES+=kern/term.c kern/device.c
KERNFILES+=kern/err.c
KERNFILES+=kern/env.c kern/disk.c
KERNFILES+=kern/fs.c kern/misc.c
KERNFILES+=kern/time.c
KERNFILES+=kern/list.c kern/partition.c
KERNFILES+=fs/fshelp.c fs/ext2.c
KERNFILES+=main.c
KERNOBJS=$(subst .c,.o,${KERNFILES})
CFLAGS=-Iinclude -g
BIN=test${EXT_EXE}
all: ${KERNOBJS} ${BIN}
${BIN}:
${CC} -o ${BIN} ${CFLAGS} ${KERNOBJS}
lib: all libgrubfs.a
libgrubfs.a:
rm -f libgrubfs.a
ar -q libgrubfs.a ${KERNOBJS}
clean:
rm -f ${KERNOBJS} ${BIN}
rm -f libgrubfs.a

3
libr/fs/p/grub/TODO Normal file
View File

@ -0,0 +1,3 @@
* Reduce the number of needed include files
* Add a sync method
* Use libtrum (from netbsd?)

Binary file not shown.

553
libr/fs/p/grub/fs/affs.c Normal file
View File

@ -0,0 +1,553 @@
/* affs.c - Amiga Fast FileSystem. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
/* The affs bootblock. */
struct grub_affs_bblock
{
grub_uint8_t type[3];
grub_uint8_t flags;
grub_uint32_t checksum;
grub_uint32_t rootblock;
} __attribute__ ((packed));
/* Set if the filesystem is a AFFS filesystem. Otherwise this is an
OFS filesystem. */
#define GRUB_AFFS_FLAG_FFS 1
/* The affs rootblock. */
struct grub_affs_rblock
{
grub_uint8_t type[4];
grub_uint8_t unused1[8];
grub_uint32_t htsize;
grub_uint32_t unused2;
grub_uint32_t checksum;
grub_uint32_t hashtable[1];
} __attribute__ ((packed));
/* The second part of a file header block. */
struct grub_affs_file
{
grub_uint8_t unused1[12];
grub_uint32_t size;
grub_uint8_t unused2[104];
grub_uint8_t namelen;
grub_uint8_t name[30];
grub_uint8_t unused3[33];
grub_uint32_t next;
grub_uint32_t parent;
grub_uint32_t extension;
grub_int32_t type;
} __attribute__ ((packed));
/* The location of `struct grub_affs_file' relative to the end of a
file header block. */
#define GRUB_AFFS_FILE_LOCATION 200
/* The offset in both the rootblock and the file header block for the
hashtable, symlink and block pointers (all synonyms). */
#define GRUB_AFFS_HASHTABLE_OFFSET 24
#define GRUB_AFFS_BLOCKPTR_OFFSET 24
#define GRUB_AFFS_SYMLINK_OFFSET 24
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
#define GRUB_AFFS_FILETYPE_DIR -3
#define GRUB_AFFS_FILETYPE_REG 2
#define GRUB_AFFS_FILETYPE_SYMLINK 3
struct grub_fshelp_node
{
struct grub_affs_data *data;
int block;
int size;
int parent;
};
/* Information about a "mounted" affs filesystem. */
struct grub_affs_data
{
struct grub_affs_bblock bblock;
struct grub_fshelp_node diropen;
grub_disk_t disk;
/* Blocksize in sectors. */
int blocksize;
/* The number of entries in the hashtable. */
int htsize;
};
static grub_dl_t my_mod;
static grub_disk_addr_t
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
int links;
grub_uint32_t pos;
int block = node->block;
struct grub_affs_file file;
struct grub_affs_data *data = node->data;
grub_uint32_t mod;
/* Find the block that points to the fileblock we are looking up by
following the chain until the right table is reached. */
for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
{
grub_disk_read (data->disk, block + data->blocksize - 1,
data->blocksize * (GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file);
if (grub_errno)
return 0;
block = grub_be_to_cpu32 (file.extension);
}
/* Translate the fileblock to the block within the right table. */
fileblock = mod;
grub_disk_read (data->disk, block,
GRUB_AFFS_BLOCKPTR_OFFSET
+ (data->htsize - fileblock - 1) * sizeof (pos),
sizeof (pos), &pos);
if (grub_errno)
return 0;
return grub_be_to_cpu32 (pos);
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_affs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_affs_read_block,
node->size, 0);
}
static struct grub_affs_data *
grub_affs_mount (grub_disk_t disk)
{
struct grub_affs_data *data;
grub_uint32_t *rootblock = 0;
struct grub_affs_rblock *rblock;
int checksum = 0;
int checksumr = 0;
int blocksize = 0;
data = grub_malloc (sizeof (struct grub_affs_data));
if (!data)
return 0;
/* Read the bootblock. */
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
&data->bblock);
if (grub_errno)
goto fail;
/* Make sure this is an affs filesystem. */
if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3))
{
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
goto fail;
}
/* Test if the filesystem is a OFS filesystem. */
if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS))
{
grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
goto fail;
}
/* Read the bootblock. */
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
&data->bblock);
if (grub_errno)
goto fail;
/* No sane person uses more than 8KB for a block. At least I hope
for that person because in that case this won't work. */
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
if (!rootblock)
goto fail;
rblock = (struct grub_affs_rblock *) rootblock;
/* Read the rootblock. */
grub_disk_read (disk, grub_be_to_cpu32 (data->bblock.rootblock), 0,
GRUB_DISK_SECTOR_SIZE * 16, rootblock);
if (grub_errno)
goto fail;
/* The filesystem blocksize is not stored anywhere in the filesystem
itself. One way to determine it is reading blocks for the
rootblock until the checksum is correct. */
checksumr = grub_be_to_cpu32 (rblock->checksum);
rblock->checksum = 0;
for (blocksize = 0; blocksize < 8; blocksize++)
{
grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize;
unsigned int i;
for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
checksum += grub_be_to_cpu32 (currblock[i]);
if (checksumr == -checksum)
break;
}
if (-checksum != checksumr)
{
grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
goto fail;
}
blocksize++;
data->blocksize = blocksize;
data->disk = disk;
data->htsize = grub_be_to_cpu32 (rblock->htsize);
data->diropen.data = data;
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
grub_free (rootblock);
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem");
grub_free (data);
grub_free (rootblock);
return 0;
}
static char *
grub_affs_read_symlink (grub_fshelp_node_t node)
{
struct grub_affs_data *data = node->data;
char *symlink;
symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize));
if (!symlink)
return 0;
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
if (grub_errno)
{
grub_free (symlink);
return 0;
}
grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
return symlink;
}
static int
grub_affs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
int i;
struct grub_affs_file file;
struct grub_fshelp_node *node = 0;
struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable;
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
int size, int type);
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
int size, int type)
{
node = grub_malloc (sizeof (*node));
if (!node)
{
grub_free (hashtable);
return 1;
}
node->data = data;
node->size = size;
node->block = block;
node->parent = grub_be_to_cpu32 (file.parent);
if (hook (name, type, node))
{
grub_free (hashtable);
return 1;
}
return 0;
}
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
if (!hashtable)
return 1;
grub_disk_read (data->disk, dir->block, GRUB_AFFS_HASHTABLE_OFFSET,
data->htsize * sizeof (*hashtable), (char *) hashtable);
if (grub_errno)
goto fail;
/* Create the directory entries for `.' and `..'. */
if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR))
return 1;
if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block,
dir->size, GRUB_FSHELP_DIR))
return 1;
for (i = 0; i < data->htsize; i++)
{
enum grub_fshelp_filetype type;
grub_uint64_t next;
if (!hashtable[i])
continue;
/* Every entry in the hashtable can be chained. Read the entire
chain. */
next = grub_be_to_cpu32 (hashtable[i]);
while (next)
{
grub_disk_read (data->disk, next + data->blocksize - 1,
data->blocksize * GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION,
sizeof (file), (char *) &file);
if (grub_errno)
goto fail;
file.name[file.namelen] = '\0';
if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR)
type = GRUB_FSHELP_REG;
else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG)
type = GRUB_FSHELP_DIR;
else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
else
type = GRUB_FSHELP_UNKNOWN;
if (grub_affs_create_node ((char *) (file.name), next,
grub_be_to_cpu32 (file.size), type))
return 1;
next = grub_be_to_cpu32 (file.next);
}
}
grub_free (hashtable);
return 0;
fail:
grub_free (node);
grub_free (hashtable);
return 0;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_affs_open (struct grub_file *file, const char *name)
{
struct grub_affs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_affs_mount (file->device->disk);
if (!data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_affs_iterate_dir,
grub_affs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
file->size = fdiro->size;
data->diropen = *fdiro;
grub_free (fdiro);
file->data = data;
file->offset = 0;
return 0;
fail:
if (data && fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_affs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_affs_data *data =
(struct grub_affs_data *) file->data;
int size = grub_affs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
return size;
}
static grub_err_t
grub_affs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_affs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_affs_mount (device->disk);
if (!data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_affs_iterate_dir,
grub_affs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_affs_iterate_dir (fdiro, iterate);
fail:
if (data && fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_affs_label (grub_device_t device, char **label)
{
struct grub_affs_data *data;
struct grub_affs_file file;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_affs_mount (disk);
if (data)
{
/* The rootblock maps quite well on a file header block, it's
something we can use here. */
grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock),
data->blocksize * (GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file);
if (grub_errno)
return 0;
*label = grub_strndup ((char *) (file.name), file.namelen);
}
else
*label = 0;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_affs_fs =
{
.name = "affs",
.dir = grub_affs_dir,
.open = grub_affs_open,
.read = grub_affs_read,
.close = grub_affs_close,
.label = grub_affs_label,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};
GRUB_MOD_INIT(affs)
{
grub_fs_register (&grub_affs_fs);
my_mod = mod;
}
GRUB_MOD_FINI(affs)
{
grub_fs_unregister (&grub_affs_fs);
}

718
libr/fs/p/grub/fs/afs.c Normal file
View File

@ -0,0 +1,718 @@
/* afs.c - The native AtheOS file-system. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#ifdef MODE_BIGENDIAN
#define GRUB_AFS_FSNAME_SUFFIX "_be"
#else
#define GRUB_AFS_FSNAME_SUFFIX ""
#endif
#ifdef MODE_BFS
#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX
#else
#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX
#endif
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
#define GRUB_AFS_BLOCKS_PER_DI_RUN 4
#ifdef MODE_BFS
#define GRUB_AFS_SBLOCK_SECTOR 1
#define GRUB_AFS_SBLOCK_MAGIC1 0x42465331 /* BFS1. */
#else
#define GRUB_AFS_SBLOCK_SECTOR 2
#define GRUB_AFS_SBLOCK_MAGIC1 0x41465331 /* AFS1. */
#endif
#define GRUB_AFS_SBLOCK_MAGIC2 0xdd121031
#define GRUB_AFS_SBLOCK_MAGIC3 0x15b6830e
#define GRUB_AFS_INODE_MAGIC 0x64358428
#ifdef MODE_BFS
#define GRUB_AFS_BTREE_MAGIC 0x69f6c2e8
#else
#define GRUB_AFS_BTREE_MAGIC 0x65768995
#endif
#define GRUB_AFS_BNODE_SIZE 1024
#define GRUB_AFS_S_IFMT 00170000
#define GRUB_AFS_S_IFLNK 0120000
#define GRUB_AFS_S_IFREG 0100000
#define GRUB_AFS_S_IFDIR 0040000
#define GRUB_AFS_S_IFIFO 0010000
#define GRUB_AFS_NULL_VAL ((grub_afs_bvalue_t)-1)
#ifdef MODE_BIGENDIAN
#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x)
#else
#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x)
#endif
#ifdef MODE_BFS
#define B_KEY_INDEX_ALIGN 8
#else
#define B_KEY_INDEX_ALIGN 4
#endif
#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
((char *) (node) \
+ ALIGN_UP (sizeof (struct grub_afs_bnode) \
+ node->key_size, \
B_KEY_INDEX_ALIGN)))
#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
((char *) B_KEY_INDEX_OFFSET (node) + \
node->key_count * 2))
typedef grub_uint64_t grub_afs_off_t;
typedef grub_uint64_t grub_afs_bigtime;
typedef grub_uint64_t grub_afs_bvalue_t;
struct grub_afs_blockrun
{
grub_uint32_t group;
grub_uint16_t start;
grub_uint16_t len;
} __attribute__ ((packed));
struct grub_afs_datastream
{
struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
grub_afs_off_t max_direct_range;
struct grub_afs_blockrun indirect;
grub_afs_off_t max_indirect_range;
struct grub_afs_blockrun double_indirect;
grub_afs_off_t max_double_indirect_range;
grub_afs_off_t size;
} __attribute__ ((packed));
struct grub_afs_bnode
{
grub_afs_bvalue_t left;
grub_afs_bvalue_t right;
grub_afs_bvalue_t overflow;
#ifdef MODE_BFS
grub_uint16_t key_count;
grub_uint16_t key_size;
#else
grub_uint32_t key_count;
grub_uint32_t key_size;
#endif
char key_data[0];
} __attribute__ ((packed));
#ifdef MODE_BFS
struct grub_afs_btree
{
grub_uint32_t magic;
grub_uint32_t unused1;
grub_uint32_t tree_depth;
grub_uint32_t unused2;
grub_afs_bvalue_t root;
grub_uint32_t unused3[4];
} __attribute__ ((packed));
#else
struct grub_afs_btree
{
grub_uint32_t magic;
grub_afs_bvalue_t root;
grub_uint32_t tree_depth;
grub_afs_bvalue_t last_node;
grub_afs_bvalue_t first_free;
} __attribute__ ((packed));
#endif
/* Beware that following structure describes AtheFS and if you write code
which uses currently unused fields check it with both AtheFS and BeFS.
*/
struct grub_afs_sblock
{
char name[32];
grub_uint32_t magic1;
grub_uint32_t byte_order;
grub_uint32_t block_size;
grub_uint32_t block_shift;
grub_afs_off_t num_blocks;
grub_afs_off_t used_blocks;
grub_uint32_t inode_size;
grub_uint32_t magic2;
grub_uint32_t block_per_group; /* Number of blocks per allocation
group. (Max 65536) */
grub_uint32_t alloc_group_shift; /* Number of bits to shift a group
number to get a byte address. */
grub_uint32_t alloc_group_count;
grub_uint32_t flags;
struct grub_afs_blockrun log_block;
grub_afs_off_t log_start;
grub_uint32_t valid_log_blocks;
grub_uint32_t log_size;
grub_uint32_t magic3;
struct grub_afs_blockrun root_dir; /* Root dir inode. */
struct grub_afs_blockrun deleted_files; /* Directory containing files
scheduled for deletion. */
struct grub_afs_blockrun index_dir; /* Directory of index files. */
grub_uint32_t boot_loader_size;
grub_uint32_t pad[7];
} __attribute__ ((packed));
struct grub_afs_inode
{
grub_uint32_t magic1;
struct grub_afs_blockrun inode_num;
grub_uint32_t uid;
grub_uint32_t gid;
grub_uint32_t mode;
grub_uint32_t flags;
#ifndef MODE_BFS
grub_uint32_t link_count;
#endif
grub_afs_bigtime create_time;
grub_afs_bigtime modified_time;
struct grub_afs_blockrun parent;
struct grub_afs_blockrun attrib_dir;
grub_uint32_t index_type; /* Key data-key only used for index files. */
grub_uint32_t inode_size;
grub_uint32_t unused;
struct grub_afs_datastream stream;
grub_uint32_t pad[4];
grub_uint32_t small_data[1];
} __attribute__ ((packed));
struct grub_fshelp_node
{
struct grub_afs_data *data;
struct grub_afs_inode inode;
};
struct grub_afs_data
{
grub_disk_t disk;
struct grub_afs_sblock sblock;
struct grub_afs_inode *inode;
struct grub_fshelp_node diropen;
};
static grub_dl_t my_mod;
static grub_afs_off_t
grub_afs_run_to_num (struct grub_afs_sblock *sb,
struct grub_afs_blockrun *run)
{
return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group)
* sb->block_per_group + grub_afs_to_cpu16 (run->start));
}
static grub_err_t
grub_afs_read_inode (struct grub_afs_data *data,
grub_uint32_t ino, struct grub_afs_inode *inode)
{
return grub_disk_read (data->disk,
ino *
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (struct grub_afs_inode),
inode);
}
static grub_disk_addr_t
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_afs_sblock *sb = &node->data->sblock;
struct grub_afs_datastream *ds = &node->inode.stream;
if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
{
int i;
for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
{
if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len))
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
}
}
else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
int i;
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
for (i = 0; i < ds->indirect.len; i++, blk++)
{
int j;
if (grub_disk_read (node->data->disk,
blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
for (j = 0; j < ptrs_per_blk; j++)
{
if (fileblock < grub_afs_to_cpu16 (indir[j].len))
return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
fileblock -= grub_afs_to_cpu16 (indir[j].len);
}
}
}
else
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
int dblk_size = dptr_size * ptrs_per_blk;
int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
int idblk_size = idptr_size * ptrs_per_blk;
int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
int idblk = (cur_pos / idblk_size);
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &ds->double_indirect)
+ idblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
}
return 0;
}
static grub_ssize_t
grub_afs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_afs_read_block,
grub_afs_to_cpu64 (node->inode.stream.size),
node->data->sblock.block_shift
- GRUB_DISK_SECTOR_BITS);
}
static char *
grub_afs_read_symlink (grub_fshelp_node_t node)
{
char *ret;
grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size);
if (size == 0)
{
size = sizeof (node->inode.stream);
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_memcpy (ret, (char *) &(node->inode.stream),
sizeof (node->inode.stream));
return ret;
}
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_afs_read_file (node, 0, 0, size, ret);
return ret;
}
static int
grub_afs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_afs_btree head;
char node_data [GRUB_AFS_BNODE_SIZE];
struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
int i;
if ((dir->inode.stream.size == 0)
|| ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT)
!= GRUB_AFS_S_IFDIR))
return 0;
grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
if (grub_errno)
return 0;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++)
{
grub_afs_bvalue_t blk;
blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]);
grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
}
if (node->key_count)
{
grub_uint32_t cur_key = 0;
while (1)
{
int key_start, key_size;
grub_uint16_t *index;
index = B_KEY_INDEX_OFFSET (node);
key_start = (cur_key > 0)
? grub_afs_to_cpu16 (index[cur_key - 1]) : 0;
key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start;
if (key_size > 0)
{
char filename [key_size + 1];
struct grub_fshelp_node *fdiro;
int mode, type;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
if (! fdiro)
return 0;
fdiro->data = dir->data;
if (grub_afs_read_inode (dir->data,
grub_afs_to_cpu64
(B_KEY_VALUE_OFFSET (node) [cur_key]),
&fdiro->inode))
return 0;
grub_memcpy (filename, &node->key_data[key_start], key_size);
filename [key_size] = 0;
mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT);
if (mode == GRUB_AFS_S_IFDIR)
type = GRUB_FSHELP_DIR;
else if (mode == GRUB_AFS_S_IFREG)
type = GRUB_FSHELP_REG;
else if (mode == GRUB_AFS_S_IFLNK)
type = GRUB_FSHELP_SYMLINK;
else
type = GRUB_FSHELP_UNKNOWN;
if (hook (filename, type, fdiro))
return 1;
}
cur_key++;
if (cur_key >= grub_afs_to_cpu32 (node->key_count))
{
if (node->right == GRUB_AFS_NULL_VAL)
break;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
cur_key = 0;
}
}
}
return 0;
}
static int
grub_afs_validate_sblock (struct grub_afs_sblock *sb)
{
if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
{
sb->magic2 = grub_afs_to_cpu32 (sb->magic2);
sb->magic3 = grub_afs_to_cpu32 (sb->magic3);
sb->block_shift = grub_afs_to_cpu32 (sb->block_shift);
sb->block_size = grub_afs_to_cpu32 (sb->block_size);
sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks);
sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks);
sb->inode_size = grub_afs_to_cpu32 (sb->inode_size);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift);
sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->log_size = grub_afs_to_cpu32 (sb->log_size);
}
else
return 0;
if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
(sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
return 0;
#ifdef MODE_BFS
sb->block_per_group = 1 << (sb->alloc_group_shift);
#endif
if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size)
|| (sb->used_blocks > sb->num_blocks )
|| (sb->inode_size != sb->block_size)
|| (0 == sb->block_size)
#ifndef MODE_BFS
|| ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
sb->block_per_group * sb->block_size)
|| (sb->alloc_group_count * sb->block_per_group < sb->num_blocks)
|| (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size)
|| (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size)
#endif
)
return 0;
return 1;
}
static struct grub_afs_data *
grub_afs_mount (grub_disk_t disk)
{
struct grub_afs_data *data = 0;
data = grub_malloc (sizeof (struct grub_afs_data));
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
sizeof (struct grub_afs_sblock), &data->sblock))
goto fail;
if (! grub_afs_validate_sblock (&data->sblock))
goto fail;
data->diropen.data = data;
data->inode = &data->diropen.inode;
data->disk = disk;
if (grub_afs_read_inode (data,
grub_afs_run_to_num (&data->sblock,
&data->sblock.root_dir),
data->inode))
goto fail;
return data;
fail:
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
grub_free (data);
return 0;
}
static grub_err_t
grub_afs_open (struct grub_file *file, const char *name)
{
struct grub_afs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_afs_mount (file->device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
grub_free (fdiro);
file->size = grub_afs_to_cpu64 (data->inode->stream.size);
file->data = data;
file->offset = 0;
return 0;
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_afs_data *data = (struct grub_afs_data *) file->data;
return grub_afs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_afs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_afs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_afs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1;
#ifdef MODE_BFS
info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16;
#else
info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time),
1000000, 0);
#endif
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_afs_mount (device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_afs_iterate_dir (fdiro, iterate);
if (fdiro != &data->diropen)
grub_free (fdiro);
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_afs_label (grub_device_t device, char **label)
{
struct grub_afs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_afs_mount (disk);
if (data)
*label = grub_strndup (data->sblock.name, sizeof (data->sblock.name));
else
*label = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_afs_fs = {
.name = GRUB_AFS_FSNAME,
.dir = grub_afs_dir,
.open = grub_afs_open,
.read = grub_afs_read,
.close = grub_afs_close,
.label = grub_afs_label,
.next = 0
};
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_INIT (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_INIT (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_INIT (afs_be)
#else
GRUB_MOD_INIT (afs)
#endif
{
grub_fs_register (&grub_afs_fs);
my_mod = mod;
}
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_FINI (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_FINI (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_FINI (afs_be)
#else
GRUB_MOD_FINI (afs)
#endif
{
grub_fs_unregister (&grub_afs_fs);
}

View File

@ -0,0 +1,2 @@
#define MODE_BIGENDIAN 1
#include "afs.c"

3
libr/fs/p/grub/fs/befs.c Normal file
View File

@ -0,0 +1,3 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#include "afs.c"

View File

@ -0,0 +1,4 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#define MODE_BIGENDIAN 1
#include "afs.c"

132
libr/fs/p/grub/fs/btrfs.c Normal file
View File

@ -0,0 +1,132 @@
/* btrfs.c - B-tree file system. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#define BTRFS_SIGNATURE "_BHRfS_M"
struct btrfs_superblock
{
grub_uint8_t dummy1[32];
grub_uint16_t uuid[8];
grub_uint8_t dummy2[16];
grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1];
} __attribute__ ((packed));
struct grub_btrfs_data
{
struct btrfs_superblock sblock;
};
static struct grub_btrfs_data *
grub_btrfs_mount (grub_disk_t disk)
{
struct grub_btrfs_data *data = grub_malloc (sizeof (*data));
if (! data)
return NULL;
if (grub_disk_read (disk, 128, 0, sizeof (data->sblock),
&data->sblock) != GRUB_ERR_NONE)
goto fail;
if (grub_memcmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
{
grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
goto fail;
}
return data;
fail:
grub_free (data);
return NULL;
}
static grub_err_t
grub_btrfs_open (struct grub_file *file __attribute__ ((unused)),
const char *name __attribute__ ((unused)))
{
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs");
}
static grub_err_t
grub_btrfs_dir (grub_device_t device,
const char *path __attribute__ ((unused)),
int (*hook) (const char *filename,
const struct grub_dirhook_info *info)
__attribute__ ((unused)))
{
struct grub_btrfs_data *data = grub_btrfs_mount (device->disk);
if (grub_errno)
return grub_errno;
grub_free (data);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_btrfs_uuid (grub_device_t device, char **uuid)
{
struct grub_btrfs_data *data;
*uuid = NULL;
data = grub_btrfs_mount (device->disk);
if (! data)
return grub_errno;
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[0]),
grub_be_to_cpu16 (data->sblock.uuid[1]),
grub_be_to_cpu16 (data->sblock.uuid[2]),
grub_be_to_cpu16 (data->sblock.uuid[3]),
grub_be_to_cpu16 (data->sblock.uuid[4]),
grub_be_to_cpu16 (data->sblock.uuid[5]),
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_btrfs_fs =
{
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.uuid = grub_btrfs_uuid,
};
GRUB_MOD_INIT(btrfs)
{
grub_fs_register (&grub_btrfs_fs);
}
GRUB_MOD_FINI(btrfs)
{
grub_fs_unregister (&grub_btrfs_fs);
}

379
libr/fs/p/grub/fs/cpio.c Normal file
View File

@ -0,0 +1,379 @@
/* cpio.c - cpio and tar filesystem. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#ifndef MODE_USTAR
/* cpio support */
#define MAGIC_BCPIO 070707
struct head
{
grub_uint16_t magic;
grub_uint16_t dev;
grub_uint16_t ino;
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint16_t gid;
grub_uint16_t nlink;
grub_uint16_t rdev;
grub_uint16_t mtime_1;
grub_uint16_t mtime_2;
grub_uint16_t namesize;
grub_uint16_t filesize_1;
grub_uint16_t filesize_2;
} __attribute__ ((packed));
#else
/* tar support */
#define MAGIC_USTAR "ustar"
struct head
{
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
} __attribute__ ((packed));
#endif
struct grub_cpio_data
{
grub_disk_t disk;
grub_uint32_t hofs;
grub_uint32_t dofs;
grub_uint32_t size;
};
static grub_dl_t my_mod;
static grub_err_t
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
grub_uint32_t * ofs)
{
#ifndef MODE_USTAR
struct head hd;
if (grub_disk_read
(data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno;
if (hd.magic != MAGIC_BCPIO)
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
if (hd.namesize & 1)
hd.namesize++;
if ((*name = grub_malloc (hd.namesize)) == NULL)
return grub_errno;
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
hd.namesize, *name))
{
grub_free (*name);
return grub_errno;
}
if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
&& ! grub_memcmp(*name, "TRAILER!!!", 11))
{
*ofs = 0;
return GRUB_ERR_NONE;
}
data->dofs = data->hofs + sizeof (hd) + hd.namesize;
*ofs = data->dofs + data->size;
if (data->size & 1)
(*ofs)++;
#else
struct head hd;
if (grub_disk_read
(data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno;
if (!hd.name[0])
{
*ofs = 0;
return GRUB_ERR_NONE;
}
if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
if ((*name = grub_strdup (hd.name)) == NULL)
return grub_errno;
data->size = grub_strtoul (hd.size, NULL, 8);
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
#endif
return GRUB_ERR_NONE;
}
static struct grub_cpio_data *
grub_cpio_mount (grub_disk_t disk)
{
struct head hd;
struct grub_cpio_data *data;
if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
goto fail;
#ifndef MODE_USTAR
if (hd.magic != MAGIC_BCPIO)
#else
if (grub_memcmp (hd.magic, MAGIC_USTAR,
sizeof (MAGIC_USTAR) - 1))
#endif
goto fail;
data = (struct grub_cpio_data *) grub_malloc (sizeof (*data));
if (!data)
goto fail;
data->disk = disk;
return data;
fail:
grub_error (GRUB_ERR_BAD_FS, "not a "
#ifdef MODE_USTAR
"tar"
#else
"cpio"
#endif
" filesystem");
return 0;
}
static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_cpio_data *data;
grub_uint32_t ofs;
char *prev, *name;
const char *np;
int len;
grub_dl_ref (my_mod);
prev = 0;
data = grub_cpio_mount (device->disk);
if (!data)
goto fail;
np = path + 1;
len = grub_strlen (path) - 1;
data->hofs = 0;
while (1)
{
if (grub_cpio_find_file (data, &name, &ofs))
goto fail;
if (!ofs)
break;
if (grub_memcmp (np, name, len) == 0)
{
char *p, *n;
n = name + len;
if (*n == '/')
n++;
p = grub_strchr (name + len, '/');
if (p)
*p = 0;
if ((!prev) || (grub_strcmp (prev, name) != 0))
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = (p != NULL);
hook (name + len, &info);
if (prev)
grub_free (prev);
prev = name;
}
else
grub_free (name);
}
data->hofs = ofs;
}
fail:
if (prev)
grub_free (prev);
if (data)
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_cpio_open (grub_file_t file, const char *name)
{
struct grub_cpio_data *data;
grub_uint32_t ofs;
char *fn;
int i, j;
grub_dl_ref (my_mod);
data = grub_cpio_mount (file->device->disk);
if (!data)
goto fail;
data->hofs = 0;
while (1)
{
if (grub_cpio_find_file (data, &fn, &ofs))
goto fail;
if (!ofs)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
break;
}
/* Compare NAME and FN by hand in order to cope with duplicate
slashes. */
i = 0;
j = 0;
while (name[i] == '/')
i++;
while (1)
{
if (name[i] != fn[j])
goto no_match;
if (name[i] == '\0')
break;
while (name[i] == '/' && name[i+1] == '/')
i++;
i++;
j++;
}
if (name[i] != fn[j])
goto no_match;
file->data = data;
file->size = data->size;
grub_free (fn);
return GRUB_ERR_NONE;
no_match:
grub_free (fn);
data->hofs = ofs;
}
fail:
if (data)
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_cpio_data *data;
data = file->data;
return (grub_disk_read (data->disk, 0, data->dofs + file->offset,
len, buf)) ? -1 : (grub_ssize_t) len;
}
static grub_err_t
grub_cpio_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return grub_errno;
}
static struct grub_fs grub_cpio_fs = {
#ifdef MODE_USTAR
.name = "tarfs",
#else
.name = "cpiofs",
#endif
.dir = grub_cpio_dir,
.open = grub_cpio_open,
.read = grub_cpio_read,
.close = grub_cpio_close,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
};
#ifdef MODE_USTAR
GRUB_MOD_INIT (tar)
#else
GRUB_MOD_INIT (cpio)
#endif
{
grub_fs_register (&grub_cpio_fs);
my_mod = mod;
}
#ifdef MODE_USTAR
GRUB_MOD_FINI (tar)
#else
GRUB_MOD_FINI (cpio)
#endif
{
grub_fs_unregister (&grub_cpio_fs);
}

990
libr/fs/p/grub/fs/ext2.c Normal file
View File

@ -0,0 +1,990 @@
/* ext2.c - Second Extended filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/* Magic value used to identify an ext2 filesystem. */
#define EXT2_MAGIC 0xEF53
/* Amount of indirect blocks in an inode. */
#define INDIRECT_BLOCKS 12
/* Maximum length of a pathname. */
#define EXT2_PATH_MAX 4096
/* Maximum nesting of symlinks, used to prevent a loop. */
#define EXT2_MAX_SYMLINKCNT 8
/* The good old revision and the default inode size. */
#define EXT2_GOOD_OLD_REVISION 0
#define EXT2_GOOD_OLD_INODE_SIZE 128
/* Filetype used in directory entry. */
#define FILETYPE_UNKNOWN 0
#define FILETYPE_REG 1
#define FILETYPE_DIRECTORY 2
#define FILETYPE_SYMLINK 7
/* Filetype information as used in inodes. */
#define FILETYPE_INO_MASK 0170000
#define FILETYPE_INO_REG 0100000
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
/* Log2 size of ext2 block in 512 blocks. */
#define LOG2_EXT2_BLOCK_SIZE(data) \
(grub_le_to_cpu32 (data->sblock.log2_block_size) + 1)
/* Log2 size of ext2 block in bytes. */
#define LOG2_BLOCK_SIZE(data) \
(grub_le_to_cpu32 (data->sblock.log2_block_size) + 10)
/* The size of an ext2 block in bytes. */
#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data))
/* The revision level. */
#define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level)
/* The inode size. */
#define EXT2_INODE_SIZE(data) \
(EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \
? EXT2_GOOD_OLD_INODE_SIZE \
: grub_le_to_cpu16 (data->sblock.inode_size))
/* Superblock filesystem feature flags (RW compatible)
* A filesystem with any of these enabled can be read and written by a driver
* that does not understand them without causing metadata/data corruption. */
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
#define EXT2_FEATURE_COMPAT_RESIZE_INODE 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
/* Superblock filesystem feature flags (RO compatible)
* A filesystem with any of these enabled can be safely read by a driver that
* does not understand them, but should not be written to, usually because
* additional metadata is required. */
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020
#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040
/* Superblock filesystem feature flags (back-incompatible)
* A filesystem with any of these enabled should not be attempted to be read
* by a driver that does not understand them, since they usually indicate
* metadata format changes that might confuse the reader. */
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Volume is journal device */
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* Extents used */
#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080
#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
/* The set of back-incompatible features this driver DOES support. Add (OR)
* flags here as the related features are implemented into the driver. */
#define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \
| EXT4_FEATURE_INCOMPAT_EXTENTS \
| EXT4_FEATURE_INCOMPAT_FLEX_BG )
/* List of rationales for the ignored "incompatible" features:
* needs_recovery: Not really back-incompatible - was added as such to forbid
* ext2 drivers from mounting an ext3 volume with a dirty
* journal because they will ignore the journal, but the next
* ext3 driver to mount the volume will find the journal and
* replay it, potentially corrupting the metadata written by
* the ext2 drivers. Safe to ignore for this RO driver. */
#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER )
#define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U
#define EXT3_JOURNAL_DESCRIPTOR_BLOCK 1
#define EXT3_JOURNAL_COMMIT_BLOCK 2
#define EXT3_JOURNAL_SUPERBLOCK_V1 3
#define EXT3_JOURNAL_SUPERBLOCK_V2 4
#define EXT3_JOURNAL_REVOKE_BLOCK 5
#define EXT3_JOURNAL_FLAG_ESCAPE 1
#define EXT3_JOURNAL_FLAG_SAME_UUID 2
#define EXT3_JOURNAL_FLAG_DELETED 4
#define EXT3_JOURNAL_FLAG_LAST_TAG 8
#define EXT4_EXTENTS_FLAG 0x80000
/* The ext2 superblock. */
struct grub_ext2_sblock
{
grub_uint32_t total_inodes;
grub_uint32_t total_blocks;
grub_uint32_t reserved_blocks;
grub_uint32_t free_blocks;
grub_uint32_t free_inodes;
grub_uint32_t first_data_block;
grub_uint32_t log2_block_size;
grub_uint32_t log2_fragment_size;
grub_uint32_t blocks_per_group;
grub_uint32_t fragments_per_group;
grub_uint32_t inodes_per_group;
grub_uint32_t mtime;
grub_uint32_t utime;
grub_uint16_t mnt_count;
grub_uint16_t max_mnt_count;
grub_uint16_t magic;
grub_uint16_t fs_state;
grub_uint16_t error_handling;
grub_uint16_t minor_revision_level;
grub_uint32_t lastcheck;
grub_uint32_t checkinterval;
grub_uint32_t creator_os;
grub_uint32_t revision_level;
grub_uint16_t uid_reserved;
grub_uint16_t gid_reserved;
grub_uint32_t first_inode;
grub_uint16_t inode_size;
grub_uint16_t block_group_number;
grub_uint32_t feature_compatibility;
grub_uint32_t feature_incompat;
grub_uint32_t feature_ro_compat;
grub_uint16_t uuid[8];
char volume_name[16];
char last_mounted_on[64];
grub_uint32_t compression_info;
grub_uint8_t prealloc_blocks;
grub_uint8_t prealloc_dir_blocks;
grub_uint16_t reserved_gdt_blocks;
grub_uint8_t journal_uuid[16];
grub_uint32_t journal_inum;
grub_uint32_t journal_dev;
grub_uint32_t last_orphan;
grub_uint32_t hash_seed[4];
grub_uint8_t def_hash_version;
grub_uint8_t jnl_backup_type;
grub_uint16_t reserved_word_pad;
grub_uint32_t default_mount_opts;
grub_uint32_t first_meta_bg;
grub_uint32_t mkfs_time;
grub_uint32_t jnl_blocks[17];
};
/* The ext2 blockgroup. */
struct grub_ext2_block_group
{
grub_uint32_t block_id;
grub_uint32_t inode_id;
grub_uint32_t inode_table_id;
grub_uint16_t free_blocks;
grub_uint16_t free_inodes;
grub_uint16_t used_dirs;
grub_uint16_t pad;
grub_uint32_t reserved[3];
};
/* The ext2 inode. */
struct grub_ext2_inode
{
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint32_t size;
grub_uint32_t atime;
grub_uint32_t ctime;
grub_uint32_t mtime;
grub_uint32_t dtime;
grub_uint16_t gid;
grub_uint16_t nlinks;
grub_uint32_t blockcnt; /* Blocks of 512 bytes!! */
grub_uint32_t flags;
grub_uint32_t osd1;
union
{
struct datablocks
{
grub_uint32_t dir_blocks[INDIRECT_BLOCKS];
grub_uint32_t indir_block;
grub_uint32_t double_indir_block;
grub_uint32_t triple_indir_block;
} blocks;
char symlink[60];
};
grub_uint32_t version;
grub_uint32_t acl;
grub_uint32_t size_high;
grub_uint32_t fragment_addr;
grub_uint32_t osd2[3];
};
/* The header of an ext2 directory entry. */
struct ext2_dirent
{
grub_uint32_t inode;
grub_uint16_t direntlen;
grub_uint8_t namelen;
grub_uint8_t filetype;
};
struct grub_ext3_journal_header
{
grub_uint32_t magic;
grub_uint32_t block_type;
grub_uint32_t sequence;
};
struct grub_ext3_journal_revoke_header
{
struct grub_ext3_journal_header header;
grub_uint32_t count;
grub_uint32_t data[0];
};
struct grub_ext3_journal_block_tag
{
grub_uint32_t block;
grub_uint32_t flags;
};
struct grub_ext3_journal_sblock
{
struct grub_ext3_journal_header header;
grub_uint32_t block_size;
grub_uint32_t maxlen;
grub_uint32_t first;
grub_uint32_t sequence;
grub_uint32_t start;
};
#define EXT4_EXT_MAGIC 0xf30a
struct grub_ext4_extent_header
{
grub_uint16_t magic;
grub_uint16_t entries;
grub_uint16_t max;
grub_uint16_t depth;
grub_uint32_t generation;
};
struct grub_ext4_extent
{
grub_uint32_t block;
grub_uint16_t len;
grub_uint16_t start_hi;
grub_uint32_t start;
};
struct grub_ext4_extent_idx
{
grub_uint32_t block;
grub_uint32_t leaf;
grub_uint16_t leaf_hi;
grub_uint16_t unused;
};
struct grub_fshelp_node
{
struct grub_ext2_data *data;
struct grub_ext2_inode inode;
int ino;
int inode_read;
};
/* Information about a "mounted" ext2 filesystem. */
struct grub_ext2_data
{
struct grub_ext2_sblock sblock;
grub_disk_t disk;
struct grub_ext2_inode *inode;
struct grub_fshelp_node diropen;
};
static grub_dl_t my_mod;
/* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of
the mounted filesystem DATA. */
inline static grub_err_t
grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
struct grub_ext2_block_group *blkgrp)
{
return grub_disk_read (data->disk,
((grub_le_to_cpu32 (data->sblock.first_data_block) + 1)
<< LOG2_EXT2_BLOCK_SIZE (data)),
group * sizeof (struct grub_ext2_block_group),
sizeof (struct grub_ext2_block_group), blkgrp);
}
static struct grub_ext4_extent_header *
grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf,
struct grub_ext4_extent_header *ext_block,
grub_uint32_t fileblock)
{
struct grub_ext4_extent_idx *index;
while (1)
{
int i;
grub_disk_addr_t block;
index = (struct grub_ext4_extent_idx *) (ext_block + 1);
if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC)
return 0;
if (ext_block->depth == 0)
return ext_block;
for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++)
{
if (fileblock < grub_le_to_cpu32(index[i].block))
break;
}
if (--i < 0)
return 0;
block = grub_le_to_cpu16 (index[i].leaf_hi);
block = (block << 32) + grub_le_to_cpu32 (index[i].leaf);
if (grub_disk_read (data->disk,
block << LOG2_EXT2_BLOCK_SIZE (data),
0, EXT2_BLOCK_SIZE(data), buf))
return 0;
ext_block = (struct grub_ext4_extent_header *) buf;
}
}
static grub_disk_addr_t
grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_ext2_data *data = node->data;
struct grub_ext2_inode *inode = &node->inode;
int blknr = -1;
unsigned int blksz = EXT2_BLOCK_SIZE (data);
int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG)
{
char buf[EXT2_BLOCK_SIZE(data)];
struct grub_ext4_extent_header *leaf;
struct grub_ext4_extent *ext;
int i;
leaf = grub_ext4_find_leaf (data, buf,
(struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
fileblock);
if (! leaf)
{
grub_error (GRUB_ERR_BAD_FS, "invalid extent");
return -1;
}
ext = (struct grub_ext4_extent *) (leaf + 1);
for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++)
{
if (fileblock < grub_le_to_cpu32 (ext[i].block))
break;
}
if (--i >= 0)
{
fileblock -= grub_le_to_cpu32 (ext[i].block);
if (fileblock >= grub_le_to_cpu16 (ext[i].len))
return 0;
else
{
grub_disk_addr_t start;
start = grub_le_to_cpu16 (ext[i].start_hi);
start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
return fileblock + start;
}
}
else
{
grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
return -1;
}
}
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS)
blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]);
/* Indirect. */
else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
{
grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.indir_block))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
}
/* Double indirect. */
else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1))
{
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS
+ blksz / 4);
grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.double_indir_block))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[rblock / perblock]))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
}
/* triple indirect. */
else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)
+ (blksz / 4) * (blksz / 4) * (blksz / 4 + 1))
{
unsigned int perblock = blksz / 4;
unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
* (blksz / 4 + 1));
grub_uint32_t indir[blksz / 4];
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (inode->blocks.triple_indir_block))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[(rblock / perblock) / perblock]))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
if (grub_disk_read (data->disk,
((grub_disk_addr_t)
grub_le_to_cpu32 (indir[(rblock / perblock) % perblock]))
<< log2_blksz,
0, blksz, indir))
return grub_errno;
blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
}
else
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ext2fs doesn't support quadruple indirect blocks");
}
return blknr;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_ext2_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
grub_off_t pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_ext2_read_block,
grub_cpu_to_le32 (node->inode.size)
| (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32),
LOG2_EXT2_BLOCK_SIZE (node->data));
}
/* Read the inode INO for the file described by DATA into INODE. */
static grub_err_t
grub_ext2_read_inode (struct grub_ext2_data *data,
int ino, struct grub_ext2_inode *inode)
{
struct grub_ext2_block_group blkgrp;
struct grub_ext2_sblock *sblock = &data->sblock;
int inodes_per_block;
unsigned int blkno;
unsigned int blkoff;
/* It is easier to calculate if the first inode is 0. */
ino--;
grub_ext2_blockgroup (data,
ino / grub_le_to_cpu32 (sblock->inodes_per_group),
&blkgrp);
if (grub_errno)
return grub_errno;
inodes_per_block = EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data);
blkno = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
/ inodes_per_block;
blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group))
% inodes_per_block;
/* Read the inode. */
if (grub_disk_read (data->disk,
((grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno)
<< LOG2_EXT2_BLOCK_SIZE (data)),
EXT2_INODE_SIZE (data) * blkoff,
sizeof (struct grub_ext2_inode), inode))
return grub_errno;
return 0;
}
static struct grub_ext2_data *
grub_ext2_mount (grub_disk_t disk)
{
struct grub_ext2_data *data;
data = grub_malloc (sizeof (struct grub_ext2_data));
if (!data)
return 0;
/* Read the superblock. */
grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_ext2_sblock),
&data->sblock);
if (grub_errno)
goto fail;
//printf ("EXT2MAGIC %x %x\n", grub_le_to_cpu16 (data->sblock.magic), EXT2_MAGIC);
/* Make sure this is an ext2 filesystem. */
if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC)
{
grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
goto fail;
}
/* Check the FS doesn't have feature bits enabled that we don't support. */
if (grub_le_to_cpu32 (data->sblock.feature_incompat)
& ~(EXT2_DRIVER_SUPPORTED_INCOMPAT | EXT2_DRIVER_IGNORED_INCOMPAT))
{
grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features");
goto fail;
}
data->disk = disk;
data->diropen.data = data;
data->diropen.ino = 2;
data->diropen.inode_read = 1;
data->inode = &data->diropen.inode;
grub_ext2_read_inode (data, 2, data->inode);
if (grub_errno)
goto fail;
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem");
grub_free (data);
return 0;
}
static char *
grub_ext2_read_symlink (grub_fshelp_node_t node)
{
char *symlink;
struct grub_fshelp_node *diro = node;
if (! diro->inode_read)
{
grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
if (grub_errno)
return 0;
}
symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1);
if (! symlink)
return 0;
/* If the filesize of the symlink is bigger than
60 the symlink is stored in a separate block,
otherwise it is stored in the inode. */
if (grub_le_to_cpu32 (diro->inode.size) <= 60)
grub_strncpy (symlink,
diro->inode.symlink,
grub_le_to_cpu32 (diro->inode.size));
else
{
grub_ext2_read_file (diro, 0, 0,
grub_le_to_cpu32 (diro->inode.size),
symlink);
if (grub_errno)
{
grub_free (symlink);
return 0;
}
}
symlink[grub_le_to_cpu32 (diro->inode.size)] = '\0';
return symlink;
}
static int
grub_ext2_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
unsigned int fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
if (! diro->inode_read)
{
grub_ext2_read_inode (diro->data, diro->ino, &diro->inode);
if (grub_errno)
return 0;
}
/* Search the file. */
while (fpos < grub_le_to_cpu32 (diro->inode.size))
{
struct ext2_dirent dirent;
grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent),
(char *) &dirent);
if (grub_errno)
return 0;
if (dirent.direntlen == 0)
return 0;
if (dirent.namelen != 0)
{
char filename[dirent.namelen + 1];
struct grub_fshelp_node *fdiro;
enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent),
dirent.namelen, filename);
if (grub_errno)
return 0;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
if (! fdiro)
return 0;
fdiro->data = diro->data;
fdiro->ino = grub_le_to_cpu32 (dirent.inode);
filename[dirent.namelen] = '\0';
if (dirent.filetype != FILETYPE_UNKNOWN)
{
fdiro->inode_read = 0;
if (dirent.filetype == FILETYPE_DIRECTORY)
type = GRUB_FSHELP_DIR;
else if (dirent.filetype == FILETYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
else if (dirent.filetype == FILETYPE_REG)
type = GRUB_FSHELP_REG;
}
else
{
/* The filetype can not be read from the dirent, read
the inode to get more information. */
grub_ext2_read_inode (diro->data,
grub_le_to_cpu32 (dirent.inode),
&fdiro->inode);
if (grub_errno)
{
grub_free (fdiro);
return 0;
}
fdiro->inode_read = 1;
if ((grub_le_to_cpu16 (fdiro->inode.mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
type = GRUB_FSHELP_DIR;
else if ((grub_le_to_cpu16 (fdiro->inode.mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
else if ((grub_le_to_cpu16 (fdiro->inode.mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_REG)
type = GRUB_FSHELP_REG;
}
if (hook (filename, type, fdiro))
return 1;
}
fpos += grub_le_to_cpu16 (dirent.direntlen);
}
return 0;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_ext2_open (struct grub_file *file, const char *name)
{
struct grub_ext2_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_err_t err;
grub_dl_ref (my_mod);
data = grub_ext2_mount (file->device->disk);
if (! data)
{
err = grub_errno;
goto fail;
}
err = grub_fshelp_find_file (name, &data->diropen, &fdiro,
grub_ext2_iterate_dir,
grub_ext2_read_symlink, GRUB_FSHELP_REG);
if (err)
goto fail;
if (! fdiro->inode_read)
{
err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
if (err)
goto fail;
}
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode));
grub_free (fdiro);
file->size = grub_le_to_cpu32 (data->inode->size);
file->size |= ((grub_off_t) grub_le_to_cpu32 (data->inode->size_high)) << 32;
file->data = data;
file->offset = 0;
return 0;
fail:
if (fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
grub_dl_unref (my_mod);
return err;
}
static grub_err_t
grub_ext2_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_ext2_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_ext2_data *data = (struct grub_ext2_data *) file->data;
return grub_ext2_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_ext2_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_ext2_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
if (! node->inode_read)
{
grub_ext2_read_inode (data, node->ino, &node->inode);
if (!grub_errno)
node->inode_read = 1;
grub_errno = GRUB_ERR_NONE;
}
if (node->inode_read)
{
info.mtimeset = 1;
info.mtime = grub_le_to_cpu32 (node->inode.mtime);
}
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_ext2_mount (device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir,
grub_ext2_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_ext2_iterate_dir (fdiro, iterate);
fail:
if (fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_ext2_label (grub_device_t device, char **label)
{
struct grub_ext2_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_ext2_mount (disk);
if (data)
*label = grub_strndup (data->sblock.volume_name, 14);
else
*label = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_err_t
grub_ext2_uuid (grub_device_t device, char **uuid)
{
struct grub_ext2_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_ext2_mount (disk);
if (data)
{
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[0]),
grub_be_to_cpu16 (data->sblock.uuid[1]),
grub_be_to_cpu16 (data->sblock.uuid[2]),
grub_be_to_cpu16 (data->sblock.uuid[3]),
grub_be_to_cpu16 (data->sblock.uuid[4]),
grub_be_to_cpu16 (data->sblock.uuid[5]),
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
/* Get mtime. */
static grub_err_t
grub_ext2_mtime (grub_device_t device, grub_int32_t *tm)
{
struct grub_ext2_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_ext2_mount (disk);
if (!data)
*tm = 0;
else
*tm = grub_le_to_cpu32 (data->sblock.utime);
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
struct grub_fs grub_ext2_fs =
{
.name = "ext2",
.dir = grub_ext2_dir,
.open = grub_ext2_open,
.read = grub_ext2_read,
.close = grub_ext2_close,
.label = grub_ext2_label,
.uuid = grub_ext2_uuid,
.mtime = grub_ext2_mtime,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
#endif
.next = 0
};
GRUB_MOD_INIT(ext2)
{
grub_fs_register (&grub_ext2_fs);
my_mod = mod;
}
GRUB_MOD_FINI(ext2)
{
grub_fs_unregister (&grub_ext2_fs);
}

876
libr/fs/p/grub/fs/fat.c Normal file
View File

@ -0,0 +1,876 @@
/* fat.c - FAT filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/fs.h>
#include <grub/disk.h>
#include <grub/file.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/charset.h>
#define GRUB_FAT_DIR_ENTRY_SIZE 32
#define GRUB_FAT_ATTR_READ_ONLY 0x01
#define GRUB_FAT_ATTR_HIDDEN 0x02
#define GRUB_FAT_ATTR_SYSTEM 0x04
#define GRUB_FAT_ATTR_VOLUME_ID 0x08
#define GRUB_FAT_ATTR_DIRECTORY 0x10
#define GRUB_FAT_ATTR_ARCHIVE 0x20
#define GRUB_FAT_MAXFILE 256
#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
| GRUB_FAT_ATTR_HIDDEN \
| GRUB_FAT_ATTR_SYSTEM \
| GRUB_FAT_ATTR_VOLUME_ID)
#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
| GRUB_FAT_ATTR_HIDDEN \
| GRUB_FAT_ATTR_SYSTEM \
| GRUB_FAT_ATTR_DIRECTORY \
| GRUB_FAT_ATTR_ARCHIVE \
| GRUB_FAT_ATTR_VOLUME_ID)
struct grub_fat_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint16_t bytes_per_sector;
grub_uint8_t sectors_per_cluster;
grub_uint16_t num_reserved_sectors;
grub_uint8_t num_fats;
grub_uint16_t num_root_entries;
grub_uint16_t num_total_sectors_16;
grub_uint8_t media;
grub_uint16_t sectors_per_fat_16;
grub_uint16_t sectors_per_track;
grub_uint16_t num_heads;
grub_uint32_t num_hidden_sectors;
grub_uint32_t num_total_sectors_32;
union
{
struct
{
grub_uint8_t num_ph_drive;
grub_uint8_t reserved;
grub_uint8_t boot_sig;
grub_uint32_t num_serial;
grub_uint8_t label[11];
grub_uint8_t fstype[8];
} __attribute__ ((packed)) fat12_or_fat16;
struct
{
grub_uint32_t sectors_per_fat_32;
grub_uint16_t extended_flags;
grub_uint16_t fs_version;
grub_uint32_t root_cluster;
grub_uint16_t fs_info;
grub_uint16_t backup_boot_sector;
grub_uint8_t reserved[12];
grub_uint8_t num_ph_drive;
grub_uint8_t reserved1;
grub_uint8_t boot_sig;
grub_uint32_t num_serial;
grub_uint8_t label[11];
grub_uint8_t fstype[8];
} __attribute__ ((packed)) fat32;
} __attribute__ ((packed)) version_specific;
} __attribute__ ((packed));
struct grub_fat_dir_entry
{
grub_uint8_t name[11];
grub_uint8_t attr;
grub_uint8_t nt_reserved;
grub_uint8_t c_time_tenth;
grub_uint16_t c_time;
grub_uint16_t c_date;
grub_uint16_t a_date;
grub_uint16_t first_cluster_high;
grub_uint16_t w_time;
grub_uint16_t w_date;
grub_uint16_t first_cluster_low;
grub_uint32_t file_size;
} __attribute__ ((packed));
struct grub_fat_long_name_entry
{
grub_uint8_t id;
grub_uint16_t name1[5];
grub_uint8_t attr;
grub_uint8_t reserved;
grub_uint8_t checksum;
grub_uint16_t name2[6];
grub_uint16_t first_cluster;
grub_uint16_t name3[2];
} __attribute__ ((packed));
struct grub_fat_data
{
int logical_sector_bits;
grub_uint32_t num_sectors;
grub_uint16_t fat_sector;
grub_uint32_t sectors_per_fat;
int fat_size;
grub_uint32_t root_cluster;
grub_uint32_t root_sector;
grub_uint32_t num_root_sectors;
int cluster_bits;
grub_uint32_t cluster_eof_mark;
grub_uint32_t cluster_sector;
grub_uint32_t num_clusters;
grub_uint8_t attr;
grub_ssize_t file_size;
grub_uint32_t file_cluster;
grub_uint32_t cur_cluster_num;
grub_uint32_t cur_cluster;
grub_uint32_t uuid;
};
static grub_dl_t my_mod;
static int
fat_log2 (unsigned x)
{
int i;
if (x == 0)
return -1;
for (i = 0; (x & 1) == 0; i++)
x >>= 1;
if (x != 1)
return -1;
return i;
}
static struct grub_fat_data *
grub_fat_mount (grub_disk_t disk)
{
struct grub_fat_bpb bpb;
struct grub_fat_data *data = 0;
grub_uint32_t first_fat, magic;
if (! disk)
goto fail;
data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
if (! data)
goto fail;
/* Read the BPB. */
if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
goto fail;
if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
goto fail;
/* Get the sizes of logical sectors and clusters. */
data->logical_sector_bits =
fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
goto fail;
data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
if (data->cluster_bits < 0)
goto fail;
data->cluster_bits += data->logical_sector_bits;
/* Get information about FATs. */
data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
<< data->logical_sector_bits);
if (data->fat_sector == 0)
goto fail;
data->sectors_per_fat = ((bpb.sectors_per_fat_16
? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
: grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
<< data->logical_sector_bits);
if (data->sectors_per_fat == 0)
goto fail;
/* Get the number of sectors in this volume. */
data->num_sectors = ((bpb.num_total_sectors_16
? grub_le_to_cpu16 (bpb.num_total_sectors_16)
: grub_le_to_cpu32 (bpb.num_total_sectors_32))
<< data->logical_sector_bits);
if (data->num_sectors == 0)
goto fail;
/* Get information about the root directory. */
if (bpb.num_fats == 0)
goto fail;
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
data->num_root_sectors
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
* GRUB_FAT_DIR_ENTRY_SIZE
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
<< (data->logical_sector_bits));
data->cluster_sector = data->root_sector + data->num_root_sectors;
data->num_clusters = (((data->num_sectors - data->cluster_sector)
>> (data->cluster_bits + data->logical_sector_bits))
+ 2);
if (data->num_clusters <= 2)
goto fail;
if (! bpb.sectors_per_fat_16)
{
/* FAT32. */
grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
data->fat_size = 32;
data->cluster_eof_mark = 0x0ffffff8;
if (flags & 0x80)
{
/* Get an active FAT. */
unsigned active_fat = flags & 0xf;
if (active_fat > bpb.num_fats)
goto fail;
data->fat_sector += active_fat * data->sectors_per_fat;
}
if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
goto fail;
}
else
{
/* FAT12 or FAT16. */
data->root_cluster = ~0U;
if (data->num_clusters <= 4085 + 2)
{
/* FAT12. */
data->fat_size = 12;
data->cluster_eof_mark = 0x0ff8;
}
else
{
/* FAT16. */
data->fat_size = 16;
data->cluster_eof_mark = 0xfff8;
}
}
/* More sanity checks. */
if (data->num_sectors <= data->fat_sector)
goto fail;
if (grub_disk_read (disk,
data->fat_sector,
0,
sizeof (first_fat),
&first_fat))
goto fail;
first_fat = grub_le_to_cpu32 (first_fat);
if (data->fat_size == 32)
{
first_fat &= 0x0fffffff;
magic = 0x0fffff00;
}
else if (data->fat_size == 16)
{
first_fat &= 0x0000ffff;
magic = 0xff00;
}
else
{
first_fat &= 0x00000fff;
magic = 0x0f00;
}
/* Serial number. */
if (bpb.sectors_per_fat_16)
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
else
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
/* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
descriptor, even if it is a so-called superfloppy (e.g. an USB key).
The check may be too strict for this kind of stupid BIOSes, as
they overwrite the media descriptor. */
if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
goto fail;
/* Start from the root directory. */
data->file_cluster = data->root_cluster;
data->cur_cluster_num = ~0U;
data->attr = GRUB_FAT_ATTR_DIRECTORY;
return data;
fail:
grub_free (data);
grub_error (GRUB_ERR_BAD_FS, "not a FAT filesystem");
return 0;
}
static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
grub_off_t offset, grub_size_t len, char *buf)
{
grub_size_t size;
grub_uint32_t logical_cluster;
unsigned logical_cluster_bits;
grub_ssize_t ret = 0;
unsigned long sector;
/* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */
if (data->file_cluster == ~0U)
{
size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
if (size > len)
size = len;
if (grub_disk_read (disk, data->root_sector, offset, size, buf))
return -1;
return size;
}
/* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits
+ data->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits;
offset &= (1 << logical_cluster_bits) - 1;
if (logical_cluster < data->cur_cluster_num)
{
data->cur_cluster_num = 0;
data->cur_cluster = data->file_cluster;
}
while (len)
{
while (logical_cluster > data->cur_cluster_num)
{
/* Find next cluster. */
grub_uint32_t next_cluster;
unsigned long fat_offset;
switch (data->fat_size)
{
case 32:
fat_offset = data->cur_cluster << 2;
break;
case 16:
fat_offset = data->cur_cluster << 1;
break;
default:
/* case 12: */
fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
break;
}
/* Read the FAT. */
if (grub_disk_read (disk, data->fat_sector, fat_offset,
(data->fat_size + 7) >> 3,
(char *) &next_cluster))
return -1;
next_cluster = grub_le_to_cpu32 (next_cluster);
switch (data->fat_size)
{
case 16:
next_cluster &= 0xFFFF;
break;
case 12:
if (data->cur_cluster & 1)
next_cluster >>= 4;
next_cluster &= 0x0FFF;
break;
}
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
data->fat_size, next_cluster);
/* Check the end. */
if (next_cluster >= data->cluster_eof_mark)
return ret;
if (next_cluster < 2 || next_cluster >= data->num_clusters)
{
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
next_cluster);
return -1;
}
data->cur_cluster = next_cluster;
data->cur_cluster_num++;
}
/* Read the data here. */
sector = (data->cluster_sector
+ ((data->cur_cluster - 2)
<< (data->cluster_bits + data->logical_sector_bits)));
size = (1 << logical_cluster_bits) - offset;
if (size > len)
size = len;
disk->read_hook = read_hook;
grub_disk_read (disk, sector, offset, size, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
len -= size;
buf += size;
ret += size;
logical_cluster++;
offset = 0;
}
return ret;
}
static grub_err_t
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
int (*hook) (const char *filename,
struct grub_fat_dir_entry *dir))
{
struct grub_fat_dir_entry dir;
char *filename, *filep = 0;
grub_uint16_t *unibuf;
int slot = -1, slots = -1;
int checksum = -1;
grub_ssize_t offset = -sizeof(dir);
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
/* Allocate space enough to hold a long name. */
filename = grub_malloc (0x40 * 13 * 4 + 1);
unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
if (! filename || ! unibuf)
{
grub_free (filename);
grub_free (unibuf);
return 0;
}
while (1)
{
unsigned i;
/* Adjust the offset. */
offset += sizeof (dir);
/* Read a directory entry. */
if ((grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir) || dir.name[0] == 0))
break;
/* Handle long name entries. */
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
{
struct grub_fat_long_name_entry *long_name
= (struct grub_fat_long_name_entry *) &dir;
grub_uint8_t id = long_name->id;
if (id & 0x40)
{
id &= 0x3f;
slots = slot = id;
checksum = long_name->checksum;
}
if (id != slot || slot == 0 || checksum != long_name->checksum)
{
checksum = -1;
continue;
}
slot--;
grub_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
grub_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
grub_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
continue;
}
/* Check if this entry is valid. */
if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
continue;
/* This is a workaround for Japanese. */
if (dir.name[0] == 0x05)
dir.name[0] = 0xe5;
if (checksum != -1 && slot == 0)
{
grub_uint8_t sum;
for (sum = 0, i = 0; i < sizeof (dir.name); i++)
sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
if (sum == checksum)
{
int u;
for (u = 0; u < slots * 13; u++)
unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
slots * 13) = '\0';
if (hook (filename, &dir))
break;
checksum = -1;
continue;
}
checksum = -1;
}
/* Convert the 8.3 file name. */
filep = filename;
if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
{
for (i = 0; i < sizeof (dir.name) && dir.name[i]
&& ! grub_isspace (dir.name[i]); i++)
*filep++ = dir.name[i];
}
else
{
for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
*filep++ = grub_tolower (dir.name[i]);
*filep = '.';
for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
*++filep = grub_tolower (dir.name[i]);
if (*filep != '.')
filep++;
}
*filep = '\0';
if (hook (filename, &dir))
break;
}
grub_free (filename);
grub_free (unibuf);
return grub_errno;
}
/* Find the underlying directory or file in PATH and return the
next path. If there is no next path or an error occurs, return NULL.
If HOOK is specified, call it with each file name. */
static char *
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
char *dirname, *dirp;
int call_hook;
int found = 0;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
return 0;
if (*dirname == '\0' && call_hook)
return hook (filename, &info);
if (grub_strcasecmp (dirname, filename) == 0)
{
found = 1;
data->attr = dir->attr;
data->file_size = grub_le_to_cpu32 (dir->file_size);
data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
| grub_le_to_cpu16 (dir->first_cluster_low));
data->cur_cluster_num = ~0U;
if (call_hook)
hook (filename, &info);
return 1;
}
return 0;
}
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
return 0;
}
/* Extract a directory name. */
while (*path == '/')
path++;
dirp = grub_strchr (path, '/');
if (dirp)
{
unsigned len = dirp - path;
dirname = grub_malloc (len + 1);
if (! dirname)
return 0;
grub_memcpy (dirname, path, len);
dirname[len] = '\0';
}
else
/* This is actually a file. */
dirname = grub_strdup (path);
call_hook = (! dirp && hook);
grub_fat_iterate_dir (disk, data, iter_hook);
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
grub_free (dirname);
return found ? dirp : 0;
}
static grub_err_t
grub_fat_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk;
grub_size_t len;
char *dirname = 0;
char *p;
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (! data)
goto fail;
/* Make sure that DIRNAME terminates with '/'. */
len = grub_strlen (path);
dirname = grub_malloc (len + 1 + 1);
if (! dirname)
goto fail;
grub_memcpy (dirname, path, len);
p = dirname + len;
if (path[len - 1] != '/')
*p++ = '/';
*p = '\0';
p = dirname;
do
{
p = grub_fat_find_dir (disk, data, p, hook);
}
while (p && grub_errno == GRUB_ERR_NONE);
fail:
grub_free (dirname);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_fat_open (grub_file_t file, const char *name)
{
struct grub_fat_data *data = 0;
char *p = (char *) name;
grub_dl_ref (my_mod);
data = grub_fat_mount (file->device->disk);
if (! data)
goto fail;
do
{
p = grub_fat_find_dir (file->device->disk, data, p, 0);
if (grub_errno != GRUB_ERR_NONE)
goto fail;
}
while (p);
if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
goto fail;
}
file->data = data;
file->size = data->file_size;
return GRUB_ERR_NONE;
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
{
return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_fat_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
{
if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
{
*label = grub_strdup (filename);
return 1;
}
return 0;
}
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (! data)
goto fail;
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
return 0;
}
*label = 0;
grub_fat_iterate_dir (disk, data, iter_hook);
fail:
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_err_t
grub_fat_uuid (grub_device_t device, char **uuid)
{
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_fat_mount (disk);
if (data)
{
*uuid = grub_xasprintf ("%04x-%04x",
(grub_uint16_t) (data->uuid >> 16),
(grub_uint16_t) data->uuid);
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_fat_fs =
{
.name = "fat",
.dir = grub_fat_dir,
.open = grub_fat_open,
.read = grub_fat_read,
.close = grub_fat_close,
.label = grub_fat_label,
.uuid = grub_fat_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 1,
#endif
.next = 0
};
GRUB_MOD_INIT(fat)
{
grub_fs_register (&grub_fat_fs);
my_mod = mod;
}
GRUB_MOD_FINI(fat)
{
grub_fs_unregister (&grub_fat_fs);
}

315
libr/fs/p/grub/fs/fshelp.c Normal file
View File

@ -0,0 +1,315 @@
/* fshelp.c -- Filesystem helper functions */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/fshelp.h>
/* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
iterate over all directory entries in the current node.
READ_SYMLINK is used to read the symlink if a node is a symlink.
EXPECTTYPE is the type node that is expected by the called, an
error is generated if the node is not of the expected type. Make
sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
because GCC has a nasty bug when using regparm=3. */
grub_err_t
grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
int (*iterate_dir) (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR (*hook)
(const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)),
char *(*read_symlink) (grub_fshelp_node_t node),
enum grub_fshelp_filetype expecttype)
{
grub_err_t err;
enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR;
int symlinknest = 0;
auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
grub_fshelp_node_t currroot,
grub_fshelp_node_t *currfound);
grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath,
grub_fshelp_node_t currroot,
grub_fshelp_node_t *currfound)
{
char fpath[grub_strlen (currpath) + 1];
char *name = fpath;
char *next;
// unsigned int pos = 0;
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
grub_fshelp_node_t currnode = currroot;
grub_fshelp_node_t oldnode = currroot;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
auto void free_node (grub_fshelp_node_t node);
void free_node (grub_fshelp_node_t node)
{
if (node != rootnode && node != currroot)
grub_free (node);
}
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
if (filetype == GRUB_FSHELP_UNKNOWN ||
(grub_strcmp (name, filename) &&
(! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) ||
grub_strncasecmp (name, filename, GRUB_LONG_MAX))))
{
grub_free (node);
return 0;
}
/* The node is found, stop iterating over the nodes. */
type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
oldnode = currnode;
currnode = node;
return 1;
}
grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1);
/* Remove all leading slashes. */
while (*name == '/')
name++;
if (! *name)
{
*currfound = currnode;
return 0;
}
for (;;)
{
int found;
/* Extract the actual part from the pathname. */
next = grub_strchr (name, '/');
if (next)
{
/* Remove all leading slashes. */
while (*next == '/')
*(next++) = '\0';
}
/* At this point it is expected that the current node is a
directory, check if this is true. */
if (type != GRUB_FSHELP_DIR)
{
free_node (currnode);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
}
/* Iterate over the directory. */
found = iterate_dir (currnode, iterate);
if (! found)
{
if (grub_errno)
return grub_errno;
break;
}
/* Read in the symlink and follow it. */
if (type == GRUB_FSHELP_SYMLINK)
{
char *symlink;
/* Test if the symlink does not loop. */
if (++symlinknest == 8)
{
free_node (currnode);
free_node (oldnode);
return grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
}
symlink = read_symlink (currnode);
free_node (currnode);
if (!symlink)
{
free_node (oldnode);
return grub_errno;
}
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
{
free_node (oldnode);
oldnode = rootnode;
}
/* Lookup the node the symlink points to. */
find_file (symlink, oldnode, &currnode);
type = foundtype;
grub_free (symlink);
if (grub_errno)
{
free_node (oldnode);
return grub_errno;
}
}
free_node (oldnode);
/* Found the node! */
if (! next || *next == '\0')
{
*currfound = currnode;
foundtype = type;
return 0;
}
name = next;
}
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
}
if (!path || path[0] != '/')
{
grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
return grub_errno;
}
err = find_file (path, rootnode, foundnode);
if (err)
return err;
/* Check if the node that was found was of the expected type. */
if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
return 0;
}
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
beginning with the block POS. READ_HOOK should be set before
reading a block from the file. GET_BLOCK is used to translate file
blocks to disk blocks. The file is FILESIZE bytes big and the
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset,
unsigned length),
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize)
{
grub_disk_addr_t i, blockcnt;
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
/* Adjust LEN so it we can't read past the end of the file. */
if (pos + len > filesize)
len = filesize - pos;
blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
{
grub_disk_addr_t blknr;
int blockoff = pos & (blocksize - 1);
int blockend = blocksize;
int skipfirst = 0;
blknr = get_block (node, i);
if (grub_errno)
return -1;
blknr = blknr << log2blocksize;
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) & (blocksize - 1);
/* The last portion is exactly blocksize. */
if (! blockend)
blockend = blocksize;
}
/* First block. */
if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
/* If the block number is 0 this block is not stored on disk but
is zero filled instead. */
if (blknr)
{
disk->read_hook = read_hook;
grub_disk_read (disk, blknr, skipfirst,
blockend, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
}
else
grub_memset (buf, 0, blockend);
buf += blocksize - skipfirst;
}
return len;
}
unsigned int
grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow)
{
int mod;
*pow = 0;
while (blksize > 1)
{
mod = blksize - ((blksize >> 1) << 1);
blksize >>= 1;
/* Check if it really is a power of two. */
if (mod)
return grub_error (GRUB_ERR_BAD_NUMBER,
"the blocksize is not a power of two");
(*pow)++;
}
return GRUB_ERR_NONE;
}

1122
libr/fs/p/grub/fs/hfs.c Normal file

File diff suppressed because it is too large Load Diff

1048
libr/fs/p/grub/fs/hfsplus.c Normal file

File diff suppressed because it is too large Load Diff

897
libr/fs/p/grub/fs/iso9660.c Normal file
View File

@ -0,0 +1,897 @@
/* iso9660.c - iso9660 implementation with extensions:
SUSP, Rock Ridge. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
#define GRUB_ISO9660_FSTYPE_DIR 0040000
#define GRUB_ISO9660_FSTYPE_REG 0100000
#define GRUB_ISO9660_FSTYPE_SYMLINK 0120000
#define GRUB_ISO9660_FSTYPE_MASK 0170000
#define GRUB_ISO9660_LOG2_BLKSZ 2
#define GRUB_ISO9660_BLKSZ 2048
#define GRUB_ISO9660_RR_DOT 2
#define GRUB_ISO9660_RR_DOTDOT 4
#define GRUB_ISO9660_VOLDESC_BOOT 0
#define GRUB_ISO9660_VOLDESC_PRIMARY 1
#define GRUB_ISO9660_VOLDESC_SUPP 2
#define GRUB_ISO9660_VOLDESC_PART 3
#define GRUB_ISO9660_VOLDESC_END 255
/* The head of a volume descriptor. */
struct grub_iso9660_voldesc
{
grub_uint8_t type;
grub_uint8_t magic[5];
grub_uint8_t version;
} __attribute__ ((packed));
/* A directory entry. */
struct grub_iso9660_dir
{
grub_uint8_t len;
grub_uint8_t ext_sectors;
grub_uint32_t first_sector;
grub_uint32_t first_sector_be;
grub_uint32_t size;
grub_uint32_t size_be;
grub_uint8_t unused1[7];
grub_uint8_t flags;
grub_uint8_t unused2[6];
grub_uint8_t namelen;
} __attribute__ ((packed));
struct grub_iso9660_date
{
grub_uint8_t year[4];
grub_uint8_t month[2];
grub_uint8_t day[2];
grub_uint8_t hour[2];
grub_uint8_t minute[2];
grub_uint8_t second[2];
grub_uint8_t hundredth[2];
grub_uint8_t offset;
} __attribute__ ((packed));
/* The primary volume descriptor. Only little endian is used. */
struct grub_iso9660_primary_voldesc
{
struct grub_iso9660_voldesc voldesc;
grub_uint8_t unused1[33];
grub_uint8_t volname[32];
grub_uint8_t unused2[16];
grub_uint8_t escape[32];
grub_uint8_t unused3[12];
grub_uint32_t path_table_size;
grub_uint8_t unused4[4];
grub_uint32_t path_table;
grub_uint8_t unused5[12];
struct grub_iso9660_dir rootdir;
grub_uint8_t unused6[624];
struct grub_iso9660_date created;
struct grub_iso9660_date modified;
} __attribute__ ((packed));
/* A single entry in the path table. */
struct grub_iso9660_path
{
grub_uint8_t len;
grub_uint8_t sectors;
grub_uint32_t first_sector;
grub_uint16_t parentdir;
grub_uint8_t name[0];
} __attribute__ ((packed));
/* An entry in the System Usage area of the directory entry. */
struct grub_iso9660_susp_entry
{
grub_uint8_t sig[2];
grub_uint8_t len;
grub_uint8_t version;
grub_uint8_t data[0];
} __attribute__ ((packed));
/* The CE entry. This is used to describe the next block where data
can be found. */
struct grub_iso9660_susp_ce
{
struct grub_iso9660_susp_entry entry;
grub_uint32_t blk;
grub_uint32_t blk_be;
grub_uint32_t off;
grub_uint32_t off_be;
grub_uint32_t len;
grub_uint32_t len_be;
} __attribute__ ((packed));
struct grub_iso9660_data
{
struct grub_iso9660_primary_voldesc voldesc;
grub_disk_t disk;
unsigned int first_sector;
int rockridge;
int susp_skip;
int joliet;
};
struct grub_fshelp_node
{
struct grub_iso9660_data *data;
unsigned int size;
unsigned int blk;
unsigned int dir_blk;
unsigned int dir_off;
};
static grub_dl_t my_mod;
/* Iterate over the susp entries, starting with block SUA_BLOCK on the
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
every entry. */
static grub_err_t
grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
int sua_block, int sua_pos, int sua_size,
grub_err_t (*hook)
(struct grub_iso9660_susp_entry *entry))
{
char *sua;
struct grub_iso9660_susp_entry *entry;
auto grub_err_t load_sua (void);
/* Load a part of the System Usage Area. */
grub_err_t load_sua (void)
{
sua = grub_malloc (sua_size);
if (!sua)
return grub_errno;
if (grub_disk_read (data->disk, sua_block, sua_pos,
sua_size, sua))
return grub_errno;
entry = (struct grub_iso9660_susp_entry *) sua;
return 0;
}
if (load_sua ())
return grub_errno;
for (; (char *) entry < (char *) sua + sua_size - 1;
entry = (struct grub_iso9660_susp_entry *)
((char *) entry + entry->len))
{
/* The last entry. */
if (grub_strncmp ((char *) entry->sig, "ST", 2) == 0)
break;
/* Additional entries are stored elsewhere. */
if (grub_strncmp ((char *) entry->sig, "CE", 2) == 0)
{
struct grub_iso9660_susp_ce *ce;
ce = (struct grub_iso9660_susp_ce *) entry;
sua_size = grub_le_to_cpu32 (ce->len);
sua_pos = grub_le_to_cpu32 (ce->off);
sua_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ;
grub_free (sua);
if (load_sua ())
return grub_errno;
}
if (hook (entry))
{
grub_free (sua);
return 0;
}
}
grub_free (sua);
return 0;
}
static char *
grub_iso9660_convert_string (grub_uint16_t *us, int len)
{
char *p;
int i;
p = grub_malloc (len * 4 + 1);
if (! p)
return p;
for (i=0; i<len; i++)
us[i] = grub_be_to_cpu16 (us[i]);
*grub_utf16_to_utf8 ((grub_uint8_t *) p, us, len) = '\0';
return p;
}
static struct grub_iso9660_data *
grub_iso9660_mount (grub_disk_t disk)
{
struct grub_iso9660_data *data = 0;
struct grub_iso9660_dir rootdir;
int sua_pos;
int sua_size;
char *sua;
struct grub_iso9660_susp_entry *entry;
struct grub_iso9660_primary_voldesc voldesc;
int block;
auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate (struct grub_iso9660_susp_entry *susp_entry)
{
/* The "ER" entry is used to detect extensions. The
`IEEE_P1285' extension means Rock ridge. */
if (grub_strncmp ((char *) susp_entry->sig, "ER", 2) == 0)
{
data->rockridge = 1;
return 1;
}
return 0;
}
data = grub_zalloc (sizeof (struct grub_iso9660_data));
if (! data)
return 0;
data->disk = disk;
block = 16;
do
{
int copy_voldesc = 0;
/* Read the superblock. */
if (grub_disk_read (disk, block << GRUB_ISO9660_LOG2_BLKSZ, 0,
sizeof (struct grub_iso9660_primary_voldesc),
(char *) &voldesc))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
if (grub_strncmp ((char *) voldesc.voldesc.magic, "CD001", 5) != 0)
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY)
copy_voldesc = 1;
else if ((voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) &&
(voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) &&
((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1. */
(voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */
(voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */
{
copy_voldesc = 1;
data->joliet = 1;
}
if (copy_voldesc)
grub_memcpy((char *) &data->voldesc, (char *) &voldesc,
sizeof (struct grub_iso9660_primary_voldesc));
block++;
} while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END);
/* Read the system use area and test it to see if SUSP is
supported. */
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
sizeof (rootdir), (char *) &rootdir))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
sua_pos = (sizeof (rootdir) + rootdir.namelen
+ (rootdir.namelen % 2) - 1);
sua_size = rootdir.len - sua_pos;
sua = grub_malloc (sua_size);
if (! sua)
goto fail;
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
sua_size, sua))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
entry = (struct grub_iso9660_susp_entry *) sua;
/* Test if the SUSP protocol is used on this filesystem. */
if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
{
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
data->susp_skip = entry->data[2];
entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
/* Iterate over the entries in the SUA area to detect
extensions. */
if (grub_iso9660_susp_iterate (data,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ),
sua_pos, sua_size, susp_iterate))
goto fail;
}
return data;
fail:
grub_free (data);
return 0;
}
static char *
grub_iso9660_read_symlink (grub_fshelp_node_t node)
{
struct grub_iso9660_dir dirent;
int sua_off;
int sua_size;
char *symlink = 0;
int addslash = 0;
auto void add_part (const char *part, int len);
auto grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *);
/* Extend the symlink. */
void add_part (const char *part, int len)
{
int size = grub_strlen (symlink);
symlink = grub_realloc (symlink, size + len + 1);
if (! symlink)
return;
grub_strncat (symlink, part, len);
}
/* Read in a symlink. */
grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry)
{
if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
{
unsigned int pos = 1;
/* The symlink is not stored as a POSIX symlink, translate it. */
while (pos < grub_le_to_cpu32 (entry->len))
{
if (addslash)
{
add_part ("/", 1);
addslash = 0;
}
/* The current position is the `Component Flag'. */
switch (entry->data[pos] & 30)
{
case 0:
{
/* The data on pos + 2 is the actual data, pos + 1
is the length. Both are part of the `Component
Record'. */
add_part ((char *) &entry->data[pos + 2],
entry->data[pos + 1]);
if ((entry->data[pos] & 1))
addslash = 1;
break;
}
case 2:
add_part ("./", 2);
break;
case 4:
add_part ("../", 3);
break;
case 8:
add_part ("/", 1);
break;
}
/* In pos + 1 the length of the `Component Record' is
stored. */
pos += entry->data[pos + 1] + 2;
}
/* Check if `grub_realloc' failed. */
if (grub_errno)
return grub_errno;
}
return 0;
}
if (grub_disk_read (node->data->disk, node->dir_blk, node->dir_off,
sizeof (dirent), (char *) &dirent))
return 0;
sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2)
+ node->data->susp_skip);
sua_size = dirent.len - sua_off;
symlink = grub_malloc (1);
if (!symlink)
return 0;
*symlink = '\0';
if (grub_iso9660_susp_iterate (node->data, node->dir_blk,
node->dir_off + sua_off,
sua_size, susp_iterate_sl))
{
grub_free (symlink);
return 0;
}
return symlink;
}
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_iso9660_dir dirent;
unsigned int offset = 0;
char *filename;
int filename_alloc = 0;
enum grub_fshelp_filetype type;
auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
{
/* The filename in the rock ridge entry. */
if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
filename = ".";
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
filename = "..";
else
{
int size = 1;
if (filename)
{
size += grub_strlen (filename);
grub_realloc (filename,
grub_strlen (filename)
+ entry->len);
}
else
{
size = entry->len - 5;
filename = grub_zalloc (size + 1);
}
filename_alloc = 1;
grub_strncpy (filename, (char *) &entry->data[1], size);
filename[size] = '\0';
}
}
/* The mode information (st_mode). */
else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
& GRUB_ISO9660_FSTYPE_MASK);
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
type = GRUB_FSHELP_DIR;
break;
case GRUB_ISO9660_FSTYPE_REG:
type = GRUB_FSHELP_REG;
break;
case GRUB_ISO9660_FSTYPE_SYMLINK:
type = GRUB_FSHELP_SYMLINK;
break;
default:
type = GRUB_FSHELP_UNKNOWN;
}
}
return 0;
}
while (offset < dir->size)
{
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE,
offset % GRUB_DISK_SECTOR_SIZE,
sizeof (dirent), (char *) &dirent))
return 0;
/* The end of the block, skip to the next one. */
if (!dirent.len)
{
offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ;
continue;
}
{
char name[dirent.namelen + 1];
int nameoffset = offset + sizeof (dirent);
struct grub_fshelp_node *node;
int sua_off = (sizeof (dirent) + dirent.namelen + 1
- (dirent.namelen % 2));
int sua_size = dirent.len - sua_off;
sua_off += offset + dir->data->susp_skip;
filename = 0;
filename_alloc = 0;
type = GRUB_FSHELP_UNKNOWN;
if (dir->data->rockridge
&& grub_iso9660_susp_iterate (dir->data,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ (sua_off
/ GRUB_DISK_SECTOR_SIZE),
sua_off % GRUB_DISK_SECTOR_SIZE,
sua_size, susp_iterate_dir))
return 0;
/* Read the name. */
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ nameoffset / GRUB_DISK_SECTOR_SIZE,
nameoffset % GRUB_DISK_SECTOR_SIZE,
dirent.namelen, (char *) name))
return 0;
node = grub_malloc (sizeof (struct grub_fshelp_node));
if (!node)
return 0;
/* Setup a new node. */
node->data = dir->data;
node->size = grub_le_to_cpu32 (dirent.size);
node->blk = grub_le_to_cpu32 (dirent.first_sector);
node->dir_blk = ((dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE);
node->dir_off = offset % GRUB_DISK_SECTOR_SIZE;
/* If the filetype was not stored using rockridge, use
whatever is stored in the iso9660 filesystem. */
if (type == GRUB_FSHELP_UNKNOWN)
{
if ((dirent.flags & 3) == 2)
type = GRUB_FSHELP_DIR;
else
type = GRUB_FSHELP_REG;
}
/* The filename was not stored in a rock ridge entry. Read it
from the iso9660 filesystem. */
if (!filename)
{
name[dirent.namelen] = '\0';
filename = grub_strrchr (name, ';');
if (filename)
*filename = '\0';
if (dirent.namelen == 1 && name[0] == 0)
filename = ".";
else if (dirent.namelen == 1 && name[0] == 1)
filename = "..";
else
filename = name;
}
if (dir->data->joliet)
{
char *oldname, *semicolon;
oldname = filename;
filename = grub_iso9660_convert_string
((grub_uint16_t *) oldname, dirent.namelen >> 1);
semicolon = grub_strrchr (filename, ';');
if (semicolon)
*semicolon = '\0';
if (filename_alloc)
grub_free (oldname);
filename_alloc = 1;
}
if (hook (filename, type, node))
{
if (filename_alloc)
grub_free (filename);
return 1;
}
if (filename_alloc)
grub_free (filename);
}
offset += dirent.len;
}
return 0;
}
static grub_err_t
grub_iso9660_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_iso9660_data *data = 0;
struct grub_fshelp_node rootnode;
struct grub_fshelp_node *foundnode;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_iso9660_mount (device->disk);
if (! data)
goto fail;
rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
/* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (path, &rootnode,
&foundnode,
grub_iso9660_iterate_dir,
grub_iso9660_read_symlink,
GRUB_FSHELP_DIR))
goto fail;
/* List the files in the directory. */
grub_iso9660_iterate_dir (foundnode, iterate);
if (foundnode != &rootnode)
grub_free (foundnode);
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_iso9660_open (struct grub_file *file, const char *name)
{
struct grub_iso9660_data *data;
struct grub_fshelp_node rootnode;
struct grub_fshelp_node *foundnode;
grub_dl_ref (my_mod);
data = grub_iso9660_mount (file->device->disk);
if (!data)
goto fail;
rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector);
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size);
/* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (name, &rootnode,
&foundnode,
grub_iso9660_iterate_dir,
grub_iso9660_read_symlink,
GRUB_FSHELP_REG))
goto fail;
data->first_sector = foundnode->blk;
file->data = data;
file->size = foundnode->size;
file->offset = 0;
return 0;
fail:
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_ssize_t
grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_iso9660_data *data =
(struct grub_iso9660_data *) file->data;
/* XXX: The file is stored in as a single extent. */
data->disk->read_hook = file->read_hook;
grub_disk_read (data->disk,
data->first_sector << GRUB_ISO9660_LOG2_BLKSZ,
file->offset,
len, buf);
data->disk->read_hook = NULL;
if (grub_errno)
return -1;
return len;
}
static grub_err_t
grub_iso9660_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_iso9660_label (grub_device_t device, char **label)
{
struct grub_iso9660_data *data;
data = grub_iso9660_mount (device->disk);
if (data)
{
if (data->joliet)
*label = grub_iso9660_convert_string
((grub_uint16_t *) &data->voldesc.volname, 16);
else
*label = grub_strndup ((char *) data->voldesc.volname, 32);
grub_free (data);
}
else
*label = 0;
return grub_errno;
}
static grub_err_t
grub_iso9660_uuid (grub_device_t device, char **uuid)
{
struct grub_iso9660_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_iso9660_mount (disk);
if (data)
{
if (! data->voldesc.modified.year[0] && ! data->voldesc.modified.year[1]
&& ! data->voldesc.modified.year[2] && ! data->voldesc.modified.year[3]
&& ! data->voldesc.modified.month[0] && ! data->voldesc.modified.month[1]
&& ! data->voldesc.modified.day[0] && ! data->voldesc.modified.day[1]
&& ! data->voldesc.modified.hour[0] && ! data->voldesc.modified.hour[1]
&& ! data->voldesc.modified.minute[0] && ! data->voldesc.modified.minute[1]
&& ! data->voldesc.modified.second[0] && ! data->voldesc.modified.second[1]
&& ! data->voldesc.modified.hundredth[0] && ! data->voldesc.modified.hundredth[1])
{
grub_error (GRUB_ERR_BAD_NUMBER, "no creation date in filesystem to generate UUID");
*uuid = NULL;
}
else
{
*uuid = grub_xasprintf ("%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c",
data->voldesc.modified.year[0],
data->voldesc.modified.year[1],
data->voldesc.modified.year[2],
data->voldesc.modified.year[3],
data->voldesc.modified.month[0],
data->voldesc.modified.month[1],
data->voldesc.modified.day[0],
data->voldesc.modified.day[1],
data->voldesc.modified.hour[0],
data->voldesc.modified.hour[1],
data->voldesc.modified.minute[0],
data->voldesc.modified.minute[1],
data->voldesc.modified.second[0],
data->voldesc.modified.second[1],
data->voldesc.modified.hundredth[0],
data->voldesc.modified.hundredth[1]);
}
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_iso9660_fs =
{
.name = "iso9660",
.dir = grub_iso9660_dir,
.open = grub_iso9660_open,
.read = grub_iso9660_read,
.close = grub_iso9660_close,
.label = grub_iso9660_label,
.uuid = grub_iso9660_uuid,
.next = 0
};
GRUB_MOD_INIT(iso9660)
{
grub_fs_register (&grub_iso9660_fs);
my_mod = mod;
}
GRUB_MOD_FINI(iso9660)
{
grub_fs_unregister (&grub_iso9660_fs);
}

899
libr/fs/p/grub/fs/jfs.c Normal file
View File

@ -0,0 +1,899 @@
/* jfs.c - JFS. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/charset.h>
#define GRUB_JFS_MAX_SYMLNK_CNT 8
#define GRUB_JFS_FILETYPE_MASK 0170000
#define GRUB_JFS_FILETYPE_REG 0100000
#define GRUB_JFS_FILETYPE_LNK 0120000
#define GRUB_JFS_FILETYPE_DIR 0040000
#define GRUB_JFS_SBLOCK 64
#define GRUB_JFS_AGGR_INODE 2
#define GRUB_JFS_FS1_INODE_BLK 104
#define GRUB_JFS_TREE_LEAF 2
struct grub_jfs_sblock
{
/* The magic for JFS. It should contain the string "JFS1". */
grub_uint8_t magic[4];
grub_uint32_t version;
grub_uint64_t ag_size;
/* The size of a filesystem block in bytes. XXX: currently only
4096 was tested. */
grub_uint32_t blksz;
grub_uint16_t log2_blksz;
grub_uint8_t unused[71];
grub_uint8_t volname[11];
grub_uint8_t unused2[32];
grub_uint8_t uuid[16];
};
struct grub_jfs_extent
{
/* The length of the extent in filesystem blocks. */
grub_uint16_t length;
grub_uint8_t length2;
/* The physical offset of the first block on the disk. */
grub_uint8_t blk1;
grub_uint32_t blk2;
} __attribute__ ((packed));
struct grub_jfs_iag
{
grub_uint8_t unused[3072];
struct grub_jfs_extent inodes[128];
} __attribute__ ((packed));
/* The head of the tree used to find extents. */
struct grub_jfs_treehead
{
grub_uint64_t next;
grub_uint64_t prev;
grub_uint8_t flags;
grub_uint8_t unused;
grub_uint16_t count;
grub_uint16_t max;
grub_uint8_t unused2[10];
} __attribute__ ((packed));
/* A node in the extent tree. */
struct grub_jfs_tree_extent
{
grub_uint8_t flags;
grub_uint16_t unused;
/* The offset is the key used to lookup an extent. */
grub_uint8_t offset1;
grub_uint32_t offset2;
struct grub_jfs_extent extent;
} __attribute__ ((packed));
/* The tree of directory entries. */
struct grub_jfs_tree_dir
{
/* Pointers to the previous and next tree headers of other nodes on
this level. */
grub_uint64_t nextb;
grub_uint64_t prevb;
grub_uint8_t flags;
/* The amount of dirents in this node. */
grub_uint8_t count;
grub_uint8_t freecnt;
grub_uint8_t freelist;
grub_uint8_t maxslot;
/* The location of the sorted array of pointers to dirents. */
grub_uint8_t sindex;
grub_uint8_t unused[10];
} __attribute__ ((packed));
/* An internal node in the dirents tree. */
struct grub_jfs_internal_dirent
{
struct grub_jfs_extent ex;
grub_uint8_t next;
grub_uint8_t len;
grub_uint16_t namepart[11];
} __attribute__ ((packed));
/* A leaf node in the dirents tree. */
struct grub_jfs_leaf_dirent
{
/* The inode for this dirent. */
grub_uint32_t inode;
grub_uint8_t next;
/* The size of the name. */
grub_uint8_t len;
grub_uint16_t namepart[11];
grub_uint32_t index;
} __attribute__ ((packed));
/* A leaf in the dirents tree. This one is used if the previously
dirent was not big enough to store the name. */
struct grub_jfs_leaf_next_dirent
{
grub_uint8_t next;
grub_uint8_t len;
grub_uint16_t namepart[15];
} __attribute__ ((packed));
struct grub_jfs_inode
{
grub_uint32_t stamp;
grub_uint32_t fileset;
grub_uint32_t inode;
grub_uint8_t unused[12];
grub_uint64_t size;
grub_uint8_t unused2[20];
grub_uint32_t mode;
grub_uint8_t unused3[72];
grub_uint8_t unused4[96];
union
{
/* The tree describing the extents of the file. */
struct __attribute__ ((packed))
{
struct grub_jfs_treehead tree;
struct grub_jfs_tree_extent extents[16];
} file;
union
{
/* The tree describing the dirents. */
struct
{
grub_uint8_t unused[16];
grub_uint8_t flags;
/* Amount of dirents in this node. */
grub_uint8_t count;
grub_uint8_t freecnt;
grub_uint8_t freelist;
grub_uint32_t idotdot;
grub_uint8_t sorted[8];
} header;
struct grub_jfs_leaf_dirent dirents[8];
} dir __attribute__ ((packed));
/* Fast symlink. */
struct
{
grub_uint8_t unused[32];
grub_uint8_t path[128];
} symlink;
} __attribute__ ((packed));
} __attribute__ ((packed));
struct grub_jfs_data
{
struct grub_jfs_sblock sblock;
grub_disk_t disk;
struct grub_jfs_inode fileset;
struct grub_jfs_inode currinode;
int pos;
int linknest;
} __attribute__ ((packed));
struct grub_jfs_diropen
{
int index;
union
{
struct grub_jfs_tree_dir header;
struct grub_jfs_leaf_dirent dirent[0];
struct grub_jfs_leaf_next_dirent next_dirent[0];
char sorted[0];
} *dirpage __attribute__ ((packed));
struct grub_jfs_data *data;
struct grub_jfs_inode *inode;
int count;
char *sorted;
struct grub_jfs_leaf_dirent *leaf;
struct grub_jfs_leaf_next_dirent *next_leaf;
/* The filename and inode of the last read dirent. */
char name[255];
grub_uint32_t ino;
} __attribute__ ((packed));
static grub_dl_t my_mod;
static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino);
/* Get the block number for the block BLK in the node INODE in the
mounted filesystem DATA. */
static int
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
unsigned int blk)
{
auto int getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents);
int getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents)
{
int found = -1;
int i;
for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++)
{
if (treehead->flags & GRUB_JFS_TREE_LEAF)
{
/* Read the leafnode. */
if (grub_le_to_cpu32 (extents[i].offset2) <= blk
&& ((grub_le_to_cpu16 (extents[i].extent.length))
+ (extents[i].extent.length2 << 8)
+ grub_le_to_cpu32 (extents[i].offset2)) > blk)
return (blk - grub_le_to_cpu32 (extents[i].offset2)
+ grub_le_to_cpu32 (extents[i].extent.blk2));
}
else
if (blk >= grub_le_to_cpu32 (extents[i].offset2))
found = i;
}
if (found != -1)
{
struct
{
struct grub_jfs_treehead treehead;
struct grub_jfs_tree_extent extents[254];
} tree;
if (grub_disk_read (data->disk,
grub_le_to_cpu32 (extents[found].extent.blk2)
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS), 0,
sizeof (tree), (char *) &tree))
return -1;
return getblk (&tree.treehead, &tree.extents[0]);
}
return -1;
}
return getblk (&inode->file.tree, &inode->file.extents[0]);
}
static grub_err_t
grub_jfs_read_inode (struct grub_jfs_data *data, int ino,
struct grub_jfs_inode *inode)
{
struct grub_jfs_iag iag;
int iagnum = ino / 4096;
int inoext = (ino % 4096) / 32;
int inonum = (ino % 4096) % 32;
grub_uint32_t iagblk;
grub_uint32_t inoblk;
iagblk = grub_jfs_blkno (data, &data->fileset, iagnum + 1);
if (grub_errno)
return grub_errno;
/* Read in the IAG. */
if (grub_disk_read (data->disk,
iagblk << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS), 0,
sizeof (struct grub_jfs_iag), &iag))
return grub_errno;
inoblk = grub_le_to_cpu32 (iag.inodes[inoext].blk2);
inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS);
inoblk += inonum;
if (grub_disk_read (data->disk, inoblk, 0,
sizeof (struct grub_jfs_inode), inode))
return grub_errno;
return 0;
}
static struct grub_jfs_data *
grub_jfs_mount (grub_disk_t disk)
{
struct grub_jfs_data *data = 0;
data = grub_malloc (sizeof (struct grub_jfs_data));
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, GRUB_JFS_SBLOCK, 0,
sizeof (struct grub_jfs_sblock), &data->sblock))
goto fail;
if (grub_strncmp ((char *) (data->sblock.magic), "JFS1", 4))
{
grub_error (GRUB_ERR_BAD_FS, "not a JFS filesystem");
goto fail;
}
data->disk = disk;
data->pos = 0;
data->linknest = 0;
/* Read the inode of the first fileset. */
if (grub_disk_read (data->disk, GRUB_JFS_FS1_INODE_BLK, 0,
sizeof (struct grub_jfs_inode), &data->fileset))
goto fail;
return data;
fail:
grub_free (data);
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not a JFS filesystem");
return 0;
}
static struct grub_jfs_diropen *
grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode)
{
struct grub_jfs_internal_dirent *de;
struct grub_jfs_diropen *diro;
int blk;
de = (struct grub_jfs_internal_dirent *) inode->dir.dirents;
if (!((grub_le_to_cpu32 (inode->mode)
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
return 0;
}
diro = grub_zalloc (sizeof (struct grub_jfs_diropen));
if (!diro)
return 0;
diro->data = data;
diro->inode = inode;
/* Check if the entire tree is contained within the inode. */
if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
{
diro->leaf = inode->dir.dirents;
diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de;
diro->sorted = (char *) (inode->dir.header.sorted);
diro->count = inode->dir.header.count;
return diro;
}
diro->dirpage = grub_malloc (grub_le_to_cpu32 (data->sblock.blksz));
if (!diro->dirpage)
{
grub_free (diro);
return 0;
}
blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2);
blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS);
/* Read in the nodes until we are on the leaf node level. */
do
{
int index;
if (grub_disk_read (data->disk, blk, 0,
grub_le_to_cpu32 (data->sblock.blksz),
diro->dirpage->sorted))
{
grub_free (diro->dirpage);
grub_free (diro);
return 0;
}
de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent;
index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
blk = (grub_le_to_cpu32 (de[index].ex.blk2)
<< (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS));
} while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF));
diro->leaf = diro->dirpage->dirent;
diro->next_leaf = diro->dirpage->next_dirent;
diro->sorted = &diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
diro->count = diro->dirpage->header.count;
return diro;
}
static void
grub_jfs_closedir (struct grub_jfs_diropen *diro)
{
if (!diro)
return;
grub_free (diro->dirpage);
grub_free (diro);
}
/* Read in the next dirent from the directory described by DIRO. */
static grub_err_t
grub_jfs_getent (struct grub_jfs_diropen *diro)
{
int strpos = 0;
struct grub_jfs_leaf_dirent *leaf;
struct grub_jfs_leaf_next_dirent *next_leaf;
int len;
int nextent;
grub_uint16_t filename[255];
auto void addstr (grub_uint16_t *uname, int ulen);
/* Add the unicode string to the utf16 filename buffer. */
void addstr (grub_uint16_t *name, int ulen)
{
while (ulen--)
filename[strpos++] = *(name++);
}
/* The last node, read in more. */
if (diro->index == diro->count)
{
unsigned int next;
/* If the inode contains the entry tree or if this was the last
node, there is nothing to read. */
if ((diro->inode->file.tree.flags & GRUB_JFS_TREE_LEAF)
|| !grub_le_to_cpu64 (diro->dirpage->header.nextb))
return GRUB_ERR_OUT_OF_RANGE;
next = grub_le_to_cpu64 (diro->dirpage->header.nextb);
next <<= (grub_le_to_cpu16 (diro->data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS);
if (grub_disk_read (diro->data->disk, next, 0,
grub_le_to_cpu32 (diro->data->sblock.blksz),
diro->dirpage->sorted))
return grub_errno;
diro->leaf = diro->dirpage->dirent;
diro->next_leaf = diro->dirpage->next_dirent;
diro->sorted = &diro->dirpage->sorted[diro->dirpage->header.sindex * 32];
diro->count = diro->dirpage->header.count;
diro->index = 0;
}
leaf = &diro->leaf[(int) diro->sorted[diro->index]];
next_leaf = &diro->next_leaf[diro->index];
len = leaf->len;
if (!len)
{
diro->index++;
return grub_jfs_getent (diro);
}
addstr (leaf->namepart, len < 11 ? len : 11);
diro->ino = grub_le_to_cpu32 (leaf->inode);
len -= 11;
/* Move down to the leaf level. */
nextent = leaf->next;
if (leaf->next != 255)
do
{
next_leaf = &diro->next_leaf[nextent];
addstr (next_leaf->namepart, len < 15 ? len : 15 );
len -= 15;
nextent = next_leaf->next;
} while (next_leaf->next != 255 && len > 0);
diro->index++;
/* Convert the temporary UTF16 filename to UTF8. */
*grub_utf16_to_utf8 ((grub_uint8_t *) (diro->name), filename, strpos) = '\0';
return 0;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_jfs_read_file (struct grub_jfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
int i;
int blockcnt;
blockcnt = ((len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1)
/ grub_le_to_cpu32 (data->sblock.blksz));
for (i = pos / grub_le_to_cpu32 (data->sblock.blksz); i < blockcnt; i++)
{
int blknr;
int blockoff = pos % grub_le_to_cpu32 (data->sblock.blksz);
int blockend = grub_le_to_cpu32 (data->sblock.blksz);
int skipfirst = 0;
blknr = grub_jfs_blkno (data, &data->currinode, i);
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) % grub_le_to_cpu32 (data->sblock.blksz);
if (!blockend)
blockend = grub_le_to_cpu32 (data->sblock.blksz);
}
/* First block. */
if (i == (pos / (int) grub_le_to_cpu32 (data->sblock.blksz)))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
data->disk->read_hook = read_hook;
grub_disk_read (data->disk,
blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS),
skipfirst, blockend, buf);
data->disk->read_hook = 0;
if (grub_errno)
return -1;
buf += grub_le_to_cpu32 (data->sblock.blksz) - skipfirst;
}
return len;
}
/* Find the file with the pathname PATH on the filesystem described by
DATA. */
static grub_err_t
grub_jfs_find_file (struct grub_jfs_data *data, const char *path)
{
char fpath[grub_strlen (path)];
char *name = fpath;
char *next;
struct grub_jfs_diropen *diro;
grub_strncpy (fpath, path, grub_strlen (path) + 1);
if (grub_jfs_read_inode (data, GRUB_JFS_AGGR_INODE, &data->currinode))
return grub_errno;
/* Skip the first slashes. */
while (*name == '/')
{
name++;
if (!*name)
return 0;
}
/* Extract the actual part from the pathname. */
next = grub_strchr (name, '/');
if (next)
{
while (*next == '/')
{
next[0] = '\0';
next++;
}
}
diro = grub_jfs_opendir (data, &data->currinode);
if (!diro)
return grub_errno;
for (;;)
{
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE)
break;
/* Check if the current direntry matches the current part of the
pathname. */
if (!grub_strcmp (name, diro->name))
{
int ino = diro->ino;
int dirino = grub_le_to_cpu32 (data->currinode.inode);
grub_jfs_closedir (diro);
diro = 0;
if (grub_jfs_read_inode (data, ino, &data->currinode))
break;
/* Check if this is a symlink. */
if ((grub_le_to_cpu32 (data->currinode.mode)
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK)
{
grub_jfs_lookup_symlink (data, dirino);
if (grub_errno)
return grub_errno;
}
if (!next)
return 0;
name = next;
next = grub_strchr (name, '/');
if (next)
{
next[0] = '\0';
next++;
}
/* Open this directory for reading dirents. */
diro = grub_jfs_opendir (data, &data->currinode);
if (!diro)
return grub_errno;
continue;
}
}
grub_jfs_closedir (diro);
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
return grub_errno;
}
static grub_err_t
grub_jfs_lookup_symlink (struct grub_jfs_data *data, int ino)
{
int size = grub_le_to_cpu64 (data->currinode.size);
char symlink[size + 1];
if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (size <= 128)
grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128);
else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
return grub_errno;
symlink[size] = '\0';
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
ino = 2;
/* Now load in the old inode. */
if (grub_jfs_read_inode (data, ino, &data->currinode))
return grub_errno;
grub_jfs_find_file (data, symlink);
if (grub_errno)
grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
return grub_errno;
}
static grub_err_t
grub_jfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_jfs_data *data = 0;
struct grub_jfs_diropen *diro = 0;
grub_dl_ref (my_mod);
data = grub_jfs_mount (device->disk);
if (!data)
goto fail;
if (grub_jfs_find_file (data, path))
goto fail;
diro = grub_jfs_opendir (data, &data->currinode);
if (!diro)
goto fail;
/* Iterate over the dirents in the directory that was found. */
while (grub_jfs_getent (diro) != GRUB_ERR_OUT_OF_RANGE)
{
struct grub_jfs_inode inode;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
if (grub_jfs_read_inode (data, diro->ino, &inode))
goto fail;
info.dir = (grub_le_to_cpu32 (inode.mode)
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
if (hook (diro->name, &info))
goto fail;
}
/* XXX: GRUB_ERR_OUT_OF_RANGE is used for the last dirent. */
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_errno = 0;
fail:
grub_jfs_closedir (diro);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_jfs_open (struct grub_file *file, const char *name)
{
struct grub_jfs_data *data;
grub_dl_ref (my_mod);
data = grub_jfs_mount (file->device->disk);
if (!data)
goto fail;
grub_jfs_find_file (data, name);
if (grub_errno)
goto fail;
/* It is only possible for open regular files. */
if (! ((grub_le_to_cpu32 (data->currinode.mode)
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_REG))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
goto fail;
}
file->data = data;
file->size = grub_le_to_cpu64 (data->currinode.size);
return 0;
fail:
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_ssize_t
grub_jfs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_jfs_data *data =
(struct grub_jfs_data *) file->data;
return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf);
}
static grub_err_t
grub_jfs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_jfs_uuid (grub_device_t device, char **uuid)
{
struct grub_jfs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_jfs_mount (disk);
if (data)
{
*uuid = grub_xasprintf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x",
data->sblock.uuid[0], data->sblock.uuid[1],
data->sblock.uuid[2], data->sblock.uuid[3],
data->sblock.uuid[4], data->sblock.uuid[5],
data->sblock.uuid[6], data->sblock.uuid[7],
data->sblock.uuid[8], data->sblock.uuid[9],
data->sblock.uuid[10], data->sblock.uuid[11],
data->sblock.uuid[12], data->sblock.uuid[13],
data->sblock.uuid[14], data->sblock.uuid[15]);
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_err_t
grub_jfs_label (grub_device_t device, char **label)
{
struct grub_jfs_data *data;
data = grub_jfs_mount (device->disk);
if (data)
*label = grub_strndup ((char *) (data->sblock.volname), 11);
else
*label = 0;
return grub_errno;
}
static struct grub_fs grub_jfs_fs =
{
.name = "jfs",
.dir = grub_jfs_dir,
.open = grub_jfs_open,
.read = grub_jfs_read,
.close = grub_jfs_close,
.label = grub_jfs_label,
.uuid = grub_jfs_uuid,
.next = 0
};
GRUB_MOD_INIT(jfs)
{
grub_fs_register (&grub_jfs_fs);
my_mod = mod;
}
GRUB_MOD_FINI(jfs)
{
grub_fs_unregister (&grub_jfs_fs);
}

588
libr/fs/p/grub/fs/minix.c Normal file
View File

@ -0,0 +1,588 @@
/* minix.c - The minix filesystem, version 1 and 2. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#ifdef MODE_MINIX2
#define GRUB_MINIX_MAGIC 0x2468
#define GRUB_MINIX_MAGIC_30 0x2478
#else
#define GRUB_MINIX_MAGIC 0x137F
#define GRUB_MINIX_MAGIC_30 0x138F
#endif
#define GRUB_MINIX_BSIZE 1024U
#define GRUB_MINIX_LOG2_BSIZE 1
#define GRUB_MINIX_ROOT_INODE 1
#define GRUB_MINIX_MAX_SYMLNK_CNT 8
#define GRUB_MINIX_SBLOCK 2
#define GRUB_MINIX_IFDIR 0040000U
#define GRUB_MINIX_IFLNK 0120000U
#ifdef MODE_MINIX2
typedef grub_uint32_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu32
#else
typedef grub_uint16_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu16
#endif
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
(data->inode.dir_zones[blk]))
#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.indir_zone))
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.double_indir_zone))
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (sblock->log2_zone_size))
#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
<< grub_le_to_cpu16 (sblock->log2_zone_size))
struct grub_minix_sblock
{
grub_uint16_t inode_cnt;
grub_uint16_t zone_cnt;
grub_uint16_t inode_bmap_size;
grub_uint16_t zone_bmap_size;
grub_uint16_t first_data_zone;
grub_uint16_t log2_zone_size;
grub_uint32_t max_file_size;
grub_uint16_t magic;
};
#ifndef MODE_MINIX2
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t uid;
grub_uint16_t size;
grub_uint32_t ctime;
grub_uint8_t gid;
grub_uint8_t nlinks;
grub_uint16_t dir_zones[7];
grub_uint16_t indir_zone;
grub_uint16_t double_indir_zone;
};
#else
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t nlinks;
grub_uint16_t uid;
grub_uint16_t gid;
grub_uint32_t size;
grub_uint32_t atime;
grub_uint32_t mtime;
grub_uint32_t ctime;
grub_uint32_t dir_zones[7];
grub_uint32_t indir_zone;
grub_uint32_t double_indir_zone;
grub_uint32_t unused;
};
#endif
/* Information about a "mounted" minix filesystem. */
struct grub_minix_data
{
struct grub_minix_sblock sblock;
struct grub_minix_inode inode;
int ino;
int linknest;
grub_disk_t disk;
int filename_size;
};
static grub_dl_t my_mod;
static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
const char *path);
static int
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{
struct grub_minix_sblock *sblock = &data->sblock;
int indir;
auto int grub_get_indir (int, int);
/* Read the block pointer in ZONE, on the offset NUM. */
int grub_get_indir (int zone, int num)
{
grub_minix_uintn_t indirn;
grub_disk_read (data->disk,
zone << GRUB_MINIX_LOG2_ZONESZ,
sizeof (grub_minix_uintn_t) * num,
sizeof (grub_minix_uintn_t), (char *) &indirn);
return grub_minix_le_to_cpu_n (indirn);
}
/* Direct block. */
if (blk < 7)
return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
/* Indirect block. */
blk -= 7;
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
{
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
return indir;
}
/* Double indirect block. */
blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data);
if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
* (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
{
indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
blk / GRUB_MINIX_ZONESZ);
indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ);
return indir;
}
/* This should never happen. */
grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size");
return 0;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_minix_read_file (struct grub_minix_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_disk_addr_t len, char *buf)
{
struct grub_minix_sblock *sblock = &data->sblock;
int i;
int blockcnt;
/* Adjust len so it we can't read past the end of the file. */
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos;
blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE;
for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++)
{
int blknr;
int blockoff = pos % GRUB_MINIX_BSIZE;
int blockend = GRUB_MINIX_BSIZE;
int skipfirst = 0;
blknr = grub_minix_get_file_block (data, i);
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) % GRUB_MINIX_BSIZE;
if (!blockend)
blockend = GRUB_MINIX_BSIZE;
}
/* First block. */
if (i == (pos / (int) GRUB_MINIX_BSIZE))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
data->disk->read_hook = read_hook;
grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
skipfirst, blockend, buf);
data->disk->read_hook = 0;
if (grub_errno)
return -1;
buf += GRUB_MINIX_BSIZE - skipfirst;
}
return len;
}
/* Read inode INO from the mounted filesystem described by DATA. This
inode is used by default now. */
static grub_err_t
grub_minix_read_inode (struct grub_minix_data *data, int ino)
{
struct grub_minix_sblock *sblock = &data->sblock;
/* Block in which the inode is stored. */
int block;
data->ino = ino;
/* The first inode in minix is inode 1. */
ino--;
block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
+ grub_le_to_cpu16 (sblock->zone_bmap_size))
<< GRUB_MINIX_LOG2_BSIZE);
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode))
* sizeof (struct grub_minix_inode));
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix_inode), &data->inode);
return GRUB_ERR_NONE;
}
/* Lookup the symlink the current inode points to. INO is the inode
number of the directory the symlink is relative to. */
static grub_err_t
grub_minix_lookup_symlink (struct grub_minix_data *data, int ino)
{
char symlink[GRUB_MINIX_INODE_SIZE (data) + 1];
if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (grub_minix_read_file (data, 0, 0,
GRUB_MINIX_INODE_SIZE (data), symlink) < 0)
return grub_errno;
symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0';
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
ino = GRUB_MINIX_ROOT_INODE;
/* Now load in the old inode. */
if (grub_minix_read_inode (data, ino))
return grub_errno;
grub_minix_find_file (data, symlink);
if (grub_errno)
grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
return grub_errno;
}
/* Find the file with the pathname PATH on the filesystem described by
DATA. */
static grub_err_t
grub_minix_find_file (struct grub_minix_data *data, const char *path)
{
char fpath[grub_strlen (path) + 1];
char *name = fpath;
char *next;
unsigned int pos = 0;
int dirino;
grub_strcpy (fpath, path);
/* Skip the first slash. */
if (name[0] == '/')
{
name++;
if (!*name)
return 0;
}
/* Extract the actual part from the pathname. */
next = grub_strchr (name, '/');
if (next)
{
next[0] = '\0';
next++;
}
do
{
grub_uint16_t ino;
char filename[data->filename_size + 1];
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
if (grub_minix_read_file (data, 0, pos, sizeof (ino),
(char *) &ino) < 0)
return grub_errno;
if (grub_minix_read_file (data, 0, pos + sizeof (ino),
data->filename_size, (char *) filename)< 0)
return grub_errno;
filename[data->filename_size] = '\0';
/* Check if the current direntry matches the current part of the
pathname. */
if (!grub_strcmp (name, filename))
{
dirino = data->ino;
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
/* Follow the symlink. */
if ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK)
{
grub_minix_lookup_symlink (data, dirino);
if (grub_errno)
return grub_errno;
}
if (!next)
return 0;
pos = 0;
name = next;
next = grub_strchr (name, '/');
if (next)
{
next[0] = '\0';
next++;
}
if ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
continue;
}
pos += sizeof (ino) + data->filename_size;
} while (pos < GRUB_MINIX_INODE_SIZE (data));
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
return grub_errno;
}
/* Mount the filesystem on the disk DISK. */
static struct grub_minix_data *
grub_minix_mount (grub_disk_t disk)
{
struct grub_minix_data *data;
data = grub_malloc (sizeof (struct grub_minix_data));
if (!data)
return 0;
/* Read the superblock. */
grub_disk_read (disk, GRUB_MINIX_SBLOCK, 0,
sizeof (struct grub_minix_sblock),&data->sblock);
if (grub_errno)
goto fail;
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
data->filename_size = 14;
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
data->filename_size = 30;
else
goto fail;
data->disk = disk;
data->linknest = 0;
return data;
fail:
grub_free (data);
#ifdef MODE_MINIX2
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
#else
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
#endif
return 0;
}
static grub_err_t
grub_minix_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_minix_data *data = 0;
unsigned int pos = 0;
data = grub_minix_mount (device->disk);
if (!data)
return grub_errno;
grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
if (grub_errno)
goto fail;
grub_minix_find_file (data, path);
if (grub_errno)
goto fail;
if ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
goto fail;
}
while (pos < GRUB_MINIX_INODE_SIZE (data))
{
grub_uint16_t ino;
char filename[data->filename_size + 1];
int dirino = data->ino;
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
if (grub_minix_read_file (data, 0, pos, sizeof (ino),
(char *) &ino) < 0)
return grub_errno;
if (grub_minix_read_file (data, 0, pos + sizeof (ino),
data->filename_size,
(char *) filename) < 0)
return grub_errno;
filename[data->filename_size] = '\0';
/* The filetype is not stored in the dirent. Read the inode to
find out the filetype. This *REALLY* sucks. */
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
if (hook (filename, &info) ? 1 : 0)
break;
/* Load the old inode back in. */
grub_minix_read_inode (data, dirino);
pos += sizeof (ino) + data->filename_size;
}
fail:
grub_free (data);
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_minix_open (struct grub_file *file, const char *name)
{
struct grub_minix_data *data;
data = grub_minix_mount (file->device->disk);
if (!data)
return grub_errno;
/* Open the inode op the root directory. */
grub_minix_read_inode (data, GRUB_MINIX_ROOT_INODE);
if (grub_errno)
{
grub_free (data);
return grub_errno;
}
if (!name || name[0] != '/')
{
grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
return grub_errno;
}
/* Traverse the directory tree to the node that should be
opened. */
grub_minix_find_file (data, name);
if (grub_errno)
{
grub_free (data);
return grub_errno;
}
file->data = data;
file->size = GRUB_MINIX_INODE_SIZE (data);
return GRUB_ERR_NONE;
}
static grub_ssize_t
grub_minix_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_minix_data *data =
(struct grub_minix_data *) file->data;
return grub_minix_read_file (data, file->read_hook, file->offset, len, buf);
}
static grub_err_t
grub_minix_close (grub_file_t file)
{
grub_free (file->data);
return GRUB_ERR_NONE;
}
static struct grub_fs grub_minix_fs =
{
#ifdef MODE_MINIX2
.name = "minix2",
#else
.name = "minix",
#endif
.dir = grub_minix_dir,
.open = grub_minix_open,
.read = grub_minix_read,
.close = grub_minix_close,
.next = 0
};
#ifdef MODE_MINIX2
GRUB_MOD_INIT(minix2)
#else
GRUB_MOD_INIT(minix)
#endif
{
grub_fs_register (&grub_minix_fs);
my_mod = mod;
}
#ifdef MODE_MINIX2
GRUB_MOD_FINI(minix2)
#else
GRUB_MOD_FINI(minix)
#endif
{
grub_fs_unregister (&grub_minix_fs);
}

View File

@ -0,0 +1,2 @@
#define MODE_MINIX2 1
#include "minix.c"

1184
libr/fs/p/grub/fs/nilfs2.c Normal file

File diff suppressed because it is too large Load Diff

1115
libr/fs/p/grub/fs/ntfs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,374 @@
/* ntfscomp.c - compression support for the NTFS filesystem */
/*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/fshelp.h>
#include <grub/ntfs.h>
static grub_err_t
decomp_nextvcn (struct grub_ntfs_comp *cc)
{
if (cc->comp_head >= cc->comp_tail)
return grub_error (GRUB_ERR_BAD_FS, "compression block overflown");
if (grub_disk_read
(cc->disk,
(cc->comp_table[cc->comp_head][1] -
(cc->comp_table[cc->comp_head][0] - cc->cbuf_vcn)) * cc->spc, 0,
cc->spc << BLK_SHR, cc->cbuf))
return grub_errno;
cc->cbuf_vcn++;
if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head][0]))
cc->comp_head++;
cc->cbuf_ofs = 0;
return 0;
}
static grub_err_t
decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res)
{
if (cc->cbuf_ofs >= (cc->spc << BLK_SHR))
{
if (decomp_nextvcn (cc))
return grub_errno;
}
*res = (unsigned char) cc->cbuf[cc->cbuf_ofs++];
return 0;
}
static grub_err_t
decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res)
{
unsigned char c1 = 0, c2 = 0;
if ((decomp_getch (cc, &c1)) || (decomp_getch (cc, &c2)))
return grub_errno;
*res = ((grub_uint16_t) c2) * 256 + ((grub_uint16_t) c1);
return 0;
}
/* Decompress a block (4096 bytes) */
static grub_err_t
decomp_block (struct grub_ntfs_comp *cc, char *dest)
{
grub_uint16_t flg, cnt;
if (decomp_get16 (cc, &flg))
return grub_errno;
cnt = (flg & 0xFFF) + 1;
if (dest)
{
if (flg & 0x8000)
{
unsigned char tag;
grub_uint32_t bits, copied;
bits = copied = tag = 0;
while (cnt > 0)
{
if (copied > COM_LEN)
return grub_error (GRUB_ERR_BAD_FS,
"compression block too large");
if (!bits)
{
if (decomp_getch (cc, &tag))
return grub_errno;
bits = 8;
cnt--;
if (cnt <= 0)
break;
}
if (tag & 1)
{
grub_uint32_t i, len, delta, code, lmask, dshift;
grub_uint16_t word;
if (decomp_get16 (cc, &word))
return grub_errno;
code = word;
cnt -= 2;
if (!copied)
{
grub_error (GRUB_ERR_BAD_FS, "nontext window empty");
return 0;
}
for (i = copied - 1, lmask = 0xFFF, dshift = 12; i >= 0x10;
i >>= 1)
{
lmask >>= 1;
dshift--;
}
delta = code >> dshift;
len = (code & lmask) + 3;
for (i = 0; i < len; i++)
{
dest[copied] = dest[copied - delta - 1];
copied++;
}
}
else
{
unsigned char ch = 0;
if (decomp_getch (cc, &ch))
return grub_errno;
dest[copied++] = ch;
cnt--;
}
tag >>= 1;
bits--;
}
return 0;
}
else
{
if (cnt != COM_LEN)
return grub_error (GRUB_ERR_BAD_FS,
"invalid compression block size");
}
}
while (cnt > 0)
{
int n;
n = (cc->spc << BLK_SHR) - cc->cbuf_ofs;
if (n > cnt)
n = cnt;
if ((dest) && (n))
{
grub_memcpy (dest, &cc->cbuf[cc->cbuf_ofs], n);
dest += n;
}
cnt -= n;
cc->cbuf_ofs += n;
if ((cnt) && (decomp_nextvcn (cc)))
return grub_errno;
}
return 0;
}
static grub_err_t
read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
{
int cpb = COM_SEC / ctx->comp.spc;
while (num)
{
int nn;
if ((ctx->target_vcn & 0xF) == 0)
{
if (ctx->comp.comp_head != ctx->comp.comp_tail)
return grub_error (GRUB_ERR_BAD_FS, "invalid compression block");
ctx->comp.comp_head = ctx->comp.comp_tail = 0;
ctx->comp.cbuf_vcn = ctx->target_vcn;
ctx->comp.cbuf_ofs = (ctx->comp.spc << BLK_SHR);
if (ctx->target_vcn >= ctx->next_vcn)
{
if (grub_ntfs_read_run_list (ctx))
return grub_errno;
}
while (ctx->target_vcn + 16 > ctx->next_vcn)
{
if (ctx->flags & RF_BLNK)
break;
ctx->comp.comp_table[ctx->comp.comp_tail][0] = ctx->next_vcn;
ctx->comp.comp_table[ctx->comp.comp_tail][1] =
ctx->curr_lcn + ctx->next_vcn - ctx->curr_vcn;
ctx->comp.comp_tail++;
if (grub_ntfs_read_run_list (ctx))
return grub_errno;
}
}
nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) / cpb;
if (nn > num)
nn = num;
num -= nn;
if (ctx->flags & RF_BLNK)
{
ctx->target_vcn += nn * cpb;
if (ctx->comp.comp_tail == 0)
{
if (buf)
{
grub_memset (buf, 0, nn * COM_LEN);
buf += nn * COM_LEN;
}
}
else
{
while (nn)
{
if (decomp_block (&ctx->comp, buf))
return grub_errno;
if (buf)
buf += COM_LEN;
nn--;
}
}
}
else
{
nn *= cpb;
while ((ctx->comp.comp_head < ctx->comp.comp_tail) && (nn))
{
int tt;
tt =
ctx->comp.comp_table[ctx->comp.comp_head][0] -
ctx->target_vcn;
if (tt > nn)
tt = nn;
ctx->target_vcn += tt;
if (buf)
{
if (grub_disk_read
(ctx->comp.disk,
(ctx->comp.comp_table[ctx->comp.comp_head][1] -
(ctx->comp.comp_table[ctx->comp.comp_head][0] -
ctx->target_vcn)) * ctx->comp.spc, 0,
tt * (ctx->comp.spc << BLK_SHR), buf))
return grub_errno;
buf += tt * (ctx->comp.spc << BLK_SHR);
}
nn -= tt;
if (ctx->target_vcn >=
ctx->comp.comp_table[ctx->comp.comp_head][0])
ctx->comp.comp_head++;
}
if (nn)
{
if (buf)
{
if (grub_disk_read
(ctx->comp.disk,
(ctx->target_vcn - ctx->curr_vcn +
ctx->curr_lcn) * ctx->comp.spc, 0,
nn * (ctx->comp.spc << BLK_SHR), buf))
return grub_errno;
buf += nn * (ctx->comp.spc << BLK_SHR);
}
ctx->target_vcn += nn;
}
}
}
return 0;
}
static grub_err_t
ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
grub_uint32_t len, struct grub_ntfs_rlst *ctx, grub_uint32_t vcn)
{
grub_err_t ret;
ctx->comp.comp_head = ctx->comp.comp_tail = 0;
ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << BLK_SHR);
if (!ctx->comp.cbuf)
return 0;
ret = 0;
//ctx->comp.disk->read_hook = read_hook;
if ((vcn > ctx->target_vcn) &&
(read_block
(ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / COM_SEC)))
{
ret = grub_errno;
goto quit;
}
if (ofs % COM_LEN)
{
grub_uint32_t t, n, o;
t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR);
if (read_block (ctx, at->sbuf, 1))
{
ret = grub_errno;
goto quit;
}
at->save_pos = t;
o = ofs % COM_LEN;
n = COM_LEN - o;
if (n > len)
n = len;
grub_memcpy (dest, &at->sbuf[o], n);
if (n == len)
goto quit;
dest += n;
len -= n;
}
if (read_block (ctx, dest, len / COM_LEN))
{
ret = grub_errno;
goto quit;
}
dest += (len / COM_LEN) * COM_LEN;
len = len % COM_LEN;
if (len)
{
grub_uint32_t t;
t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR);
if (read_block (ctx, at->sbuf, 1))
{
ret = grub_errno;
goto quit;
}
at->save_pos = t;
grub_memcpy (dest, at->sbuf, len);
}
quit:
//ctx->comp.disk->read_hook = 0;
if (ctx->comp.cbuf)
grub_free (ctx->comp.cbuf);
return ret;
}
GRUB_MOD_INIT (ntfscomp)
{
grub_ntfscomp_func = ntfscomp;
}
GRUB_MOD_FINI (ntfscomp)
{
grub_ntfscomp_func = NULL;
}

1382
libr/fs/p/grub/fs/reiserfs.c Normal file

File diff suppressed because it is too large Load Diff

597
libr/fs/p/grub/fs/sfs.c Normal file
View File

@ -0,0 +1,597 @@
/* sfs.c - Amiga Smart FileSystem. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
/* The common header for a block. */
struct grub_sfs_bheader
{
grub_uint8_t magic[4];
grub_uint32_t chksum;
grub_uint32_t ipointtomyself;
} __attribute__ ((packed));
/* The sfs rootblock. */
struct grub_sfs_rblock
{
struct grub_sfs_bheader header;
grub_uint32_t version;
grub_uint8_t unused1[36];
grub_uint32_t blocksize;
grub_uint8_t unused2[40];
grub_uint8_t unused3[8];
grub_uint32_t rootobject;
grub_uint32_t btree;
} __attribute__ ((packed));
/* A SFS object container. */
struct grub_sfs_obj
{
grub_uint8_t unused1[4];
grub_uint32_t nodeid;
grub_uint8_t unused2[4];
union
{
struct
{
grub_uint32_t first_block;
grub_uint32_t size;
} file __attribute__ ((packed));
struct
{
grub_uint32_t hashtable;
grub_uint32_t dir_objc;
} dir __attribute__ ((packed));
} file_dir;
grub_uint8_t unused3[4];
grub_uint8_t type;
grub_uint8_t filename[1];
grub_uint8_t comment[1];
} __attribute__ ((packed));
#define GRUB_SFS_TYPE_DELETED 32
#define GRUB_SFS_TYPE_SYMLINK 64
#define GRUB_SFS_TYPE_DIR 128
/* A SFS object container. */
struct grub_sfs_objc
{
struct grub_sfs_bheader header;
grub_uint32_t parent;
grub_uint32_t next;
grub_uint32_t prev;
/* The amount of objects depends on the blocksize. */
struct grub_sfs_obj objects[1];
} __attribute__ ((packed));
struct grub_sfs_btree_node
{
grub_uint32_t key;
grub_uint32_t data;
} __attribute__ ((packed));
struct grub_sfs_btree_extent
{
grub_uint32_t key;
grub_uint32_t next;
grub_uint32_t prev;
grub_uint16_t size;
} __attribute__ ((packed));
struct grub_sfs_btree
{
struct grub_sfs_bheader header;
grub_uint16_t nodes;
grub_uint8_t leaf;
grub_uint8_t nodesize;
/* Normally this can be kind of node, but just extents are
supported. */
struct grub_sfs_btree_node node[1];
} __attribute__ ((packed));
struct grub_fshelp_node
{
struct grub_sfs_data *data;
int block;
int size;
};
/* Information about a "mounted" sfs filesystem. */
struct grub_sfs_data
{
struct grub_sfs_rblock rblock;
struct grub_fshelp_node diropen;
grub_disk_t disk;
/* Blocksize in sectors. */
unsigned int blocksize;
/* Label of the filesystem. */
char *label;
};
static grub_dl_t my_mod;
/* Lookup the extent starting with BLOCK in the filesystem described
by DATA. Return the extent size in SIZE and the following extent
in NEXTEXT. */
static grub_err_t
grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block,
int *size, int *nextext)
{
char *treeblock;
struct grub_sfs_btree *tree;
int i;
int next;
treeblock = grub_malloc (data->blocksize);
if (!block)
return 0;
next = grub_be_to_cpu32 (data->rblock.btree);
tree = (struct grub_sfs_btree *) treeblock;
/* Handle this level in the btree. */
do
{
grub_disk_read (data->disk, next, 0, data->blocksize, treeblock);
if (grub_errno)
{
grub_free (treeblock);
return grub_errno;
}
for (i = grub_be_to_cpu16 (tree->nodes) - 1; i >= 0; i--)
{
#define EXTNODE(tree, index) \
((struct grub_sfs_btree_node *) (((char *) &(tree)->node[0]) \
+ (index) * (tree)->nodesize))
/* Follow the tree down to the leaf level. */
if ((grub_be_to_cpu32 (EXTNODE(tree, i)->key) <= block)
&& !tree->leaf)
{
next = grub_be_to_cpu32 (EXTNODE (tree, i)->data);
break;
}
/* If the leaf level is reached, just find the correct extent. */
if (grub_be_to_cpu32 (EXTNODE (tree, i)->key) == block && tree->leaf)
{
struct grub_sfs_btree_extent *extent;
extent = (struct grub_sfs_btree_extent *) EXTNODE (tree, i);
/* We found a correct leaf. */
*size = grub_be_to_cpu16 (extent->size);
*nextext = grub_be_to_cpu32 (extent->next);
grub_free (treeblock);
return 0;
}
#undef EXTNODE
}
} while (!tree->leaf);
grub_free (treeblock);
return grub_error (GRUB_ERR_FILE_READ_ERROR, "SFS extent not found");
}
static grub_disk_addr_t
grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
int blk = node->block;
int size = 0;
int next = 0;
while (blk)
{
grub_err_t err;
/* In case of the first block we don't have to lookup the
extent, the minimum size is always 1. */
if (fileblock == 0)
return blk;
err = grub_sfs_read_extent (node->data, blk, &size, &next);
if (err)
return 0;
if (fileblock < (unsigned int) size)
return fileblock + blk;
fileblock -= size;
blk = next;
}
grub_error (GRUB_ERR_FILE_READ_ERROR,
"reading a SFS block outside the extent");
return 0;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_sfs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_sfs_read_block,
node->size, 0);
}
static struct grub_sfs_data *
grub_sfs_mount (grub_disk_t disk)
{
struct grub_sfs_data *data;
struct grub_sfs_objc *rootobjc;
char *rootobjc_data = 0;
unsigned int blk;
data = grub_malloc (sizeof (*data));
if (!data)
return 0;
/* Read the rootblock. */
grub_disk_read (disk, 0, 0, sizeof (struct grub_sfs_rblock),
&data->rblock);
if (grub_errno)
goto fail;
/* Make sure this is a sfs filesystem. */
if (grub_strncmp ((char *) (data->rblock.header.magic), "SFS", 4))
{
grub_error (GRUB_ERR_BAD_FS, "not a SFS filesystem");
goto fail;
}
data->blocksize = grub_be_to_cpu32 (data->rblock.blocksize);
rootobjc_data = grub_malloc (data->blocksize);
if (! rootobjc_data)
goto fail;
/* Read the root object container. */
grub_disk_read (disk, grub_be_to_cpu32 (data->rblock.rootobject), 0,
data->blocksize, rootobjc_data);
if (grub_errno)
goto fail;
rootobjc = (struct grub_sfs_objc *) rootobjc_data;
blk = grub_be_to_cpu32 (rootobjc->objects[0].file_dir.dir.dir_objc);
data->diropen.size = 0;
data->diropen.block = blk;
data->diropen.data = data;
data->disk = disk;
data->label = grub_strdup ((char *) (rootobjc->objects[0].filename));
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not an SFS filesystem");
grub_free (data);
grub_free (rootobjc_data);
return 0;
}
static char *
grub_sfs_read_symlink (grub_fshelp_node_t node)
{
struct grub_sfs_data *data = node->data;
char *symlink;
char *block;
block = grub_malloc (data->blocksize);
if (!block)
return 0;
grub_disk_read (data->disk, node->block, 0, data->blocksize, block);
if (grub_errno)
{
grub_free (block);
return 0;
}
/* This is just a wild guess, but it always worked for me. How the
SLNK block looks like is not documented in the SFS docs. */
symlink = grub_strdup (&block[24]);
grub_free (block);
if (!symlink)
return 0;
return symlink;
}
static int
grub_sfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_fshelp_node *node = 0;
struct grub_sfs_data *data = dir->data;
char *objc_data;
struct grub_sfs_objc *objc;
unsigned int next = dir->block;
int pos;
auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
int size, int type);
int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
int size, int type)
{
node = grub_malloc (sizeof (*node));
if (!node)
return 1;
node->data = data;
node->size = size;
node->block = block;
return hook (name, type, node);
}
objc_data = grub_malloc (data->blocksize);
if (!objc_data)
goto fail;
/* The Object container can consist of multiple blocks, iterate over
every block. */
while (next)
{
grub_disk_read (data->disk, next, 0, data->blocksize, objc_data);
if (grub_errno)
goto fail;
objc = (struct grub_sfs_objc *) objc_data;
pos = (char *) &objc->objects[0] - (char *) objc;
/* Iterate over all entries in this block. */
while (pos + sizeof (struct grub_sfs_obj) < data->blocksize)
{
struct grub_sfs_obj *obj;
obj = (struct grub_sfs_obj *) ((char *) objc + pos);
char *filename = (char *) (obj->filename);
int len;
enum grub_fshelp_filetype type;
unsigned int block;
/* The filename and comment dynamically increase the size of
the object. */
len = grub_strlen (filename);
len += grub_strlen (filename + len + 1);
pos += sizeof (*obj) + len;
/* Round up to a multiple of two bytes. */
pos = ((pos + 1) >> 1) << 1;
if (grub_strlen (filename) == 0)
continue;
/* First check if the file was not deleted. */
if (obj->type & GRUB_SFS_TYPE_DELETED)
continue;
else if (obj->type & GRUB_SFS_TYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
else if (obj->type & GRUB_SFS_TYPE_DIR)
type = GRUB_FSHELP_DIR;
else
type = GRUB_FSHELP_REG;
if (type == GRUB_FSHELP_DIR)
block = grub_be_to_cpu32 (obj->file_dir.dir.dir_objc);
else
block = grub_be_to_cpu32 (obj->file_dir.file.first_block);
if (grub_sfs_create_node (filename, block,
grub_be_to_cpu32 (obj->file_dir.file.size),
type))
{
grub_free (objc_data);
return 1;
}
}
next = grub_be_to_cpu32 (objc->next);
}
fail:
grub_free (objc_data);
return 0;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_sfs_open (struct grub_file *file, const char *name)
{
struct grub_sfs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_sfs_mount (file->device->disk);
if (!data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_sfs_iterate_dir,
grub_sfs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
file->size = fdiro->size;
data->diropen = *fdiro;
grub_free (fdiro);
file->data = data;
file->offset = 0;
return 0;
fail:
if (data && fdiro != &data->diropen)
grub_free (fdiro);
if (data)
grub_free (data->label);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_sfs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
grub_sfs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_sfs_data *data = (struct grub_sfs_data *) file->data;
int size = grub_sfs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
return size;
}
static grub_err_t
grub_sfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_sfs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_sfs_mount (device->disk);
if (!data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_sfs_iterate_dir,
grub_sfs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_sfs_iterate_dir (fdiro, iterate);
fail:
if (data && fdiro != &data->diropen)
grub_free (fdiro);
if (data)
grub_free (data->label);
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_sfs_label (grub_device_t device, char **label)
{
struct grub_sfs_data *data;
grub_disk_t disk = device->disk;
data = grub_sfs_mount (disk);
if (data)
*label = data->label;
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_sfs_fs =
{
.name = "sfs",
.dir = grub_sfs_dir,
.open = grub_sfs_open,
.read = grub_sfs_read,
.close = grub_sfs_close,
.label = grub_sfs_label,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};
GRUB_MOD_INIT(sfs)
{
grub_fs_register (&grub_sfs_fs);
my_mod = mod;
}
GRUB_MOD_FINI(sfs)
{
grub_fs_unregister (&grub_sfs_fs);
}

2
libr/fs/p/grub/fs/tar.c Normal file
View File

@ -0,0 +1,2 @@
#define MODE_USTAR 1
#include "cpio.c"

1059
libr/fs/p/grub/fs/udf.c Normal file

File diff suppressed because it is too large Load Diff

810
libr/fs/p/grub/fs/ufs.c Normal file
View File

@ -0,0 +1,810 @@
/* ufs.c - Unix File System */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#ifdef MODE_UFS2
#define GRUB_UFS_MAGIC 0x19540119
#else
#define GRUB_UFS_MAGIC 0x11954
#endif
#define GRUB_UFS_INODE 2
#define GRUB_UFS_FILETYPE_DIR 4
#define GRUB_UFS_FILETYPE_LNK 10
#define GRUB_UFS_MAX_SYMLNK_CNT 8
#define GRUB_UFS_DIRBLKS 12
#define GRUB_UFS_INDIRBLKS 3
#define GRUB_UFS_ATTR_TYPE 0160000
#define GRUB_UFS_ATTR_FILE 0100000
#define GRUB_UFS_ATTR_DIR 0040000
#define GRUB_UFS_ATTR_LNK 0120000
#define GRUB_UFS_VOLNAME_LEN 32
/* Calculate in which group the inode can be found. */
#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize))
#define INODE(data,field) data->inode. field
#ifdef MODE_UFS2
#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits2 (data->inode.field)
#else
#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits1 (data->inode.field)
#endif
#define INODE_SIZE(data) INODE_ENDIAN (data,size,32,64)
#define INODE_NBLOCKS(data) INODE_ENDIAN (data,nblocks,32,64)
#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16)
#ifdef MODE_UFS2
#define INODE_BLKSZ 8
#else
#define INODE_BLKSZ 4
#endif
#ifdef MODE_UFS2
#define UFS_INODE_PER_BLOCK 2
#else
#define UFS_INODE_PER_BLOCK 4
#endif
#define INODE_DIRBLOCKS(data,blk) INODE_ENDIAN \
(data,blocks.dir_blocks[blk],32,64)
#define INODE_INDIRBLOCKS(data,blk) INODE_ENDIAN \
(data,blocks.indir_blocks[blk],32,64)
/* The blocks on which the superblock can be found. */
static int sblocklist[] = { 128, 16, 0, 512, -1 };
struct grub_ufs_sblock
{
grub_uint8_t unused[16];
/* The offset of the inodes in the cylinder group. */
grub_uint32_t inoblk_offs;
grub_uint8_t unused2[4];
/* The start of the cylinder group. */
grub_uint32_t cylg_offset;
grub_uint32_t cylg_mask;
grub_uint32_t mtime;
grub_uint8_t unused4[12];
/* The size of a block in bytes. */
grub_int32_t bsize;
grub_uint8_t unused5[48];
/* The size of filesystem blocks to disk blocks. */
grub_uint32_t log2_blksz;
grub_uint8_t unused6[40];
grub_uint32_t uuidhi;
grub_uint32_t uuidlow;
grub_uint8_t unused7[32];
/* Inodes stored per cylinder group. */
grub_uint32_t ino_per_group;
/* The frags per cylinder group. */
grub_uint32_t frags_per_group;
grub_uint8_t unused8[488];
/* Volume name for UFS2. */
grub_uint8_t volume_name[GRUB_UFS_VOLNAME_LEN];
grub_uint8_t unused9[360];
grub_uint64_t mtime2;
grub_uint8_t unused10[292];
/* Magic value to check if this is really a UFS filesystem. */
grub_uint32_t magic;
};
#ifdef MODE_UFS2
/* UFS inode. */
struct grub_ufs_inode
{
grub_uint16_t mode;
grub_uint16_t nlinks;
grub_uint32_t uid;
grub_uint32_t gid;
grub_uint32_t blocksize;
grub_int64_t size;
grub_int64_t nblocks;
grub_uint64_t atime;
grub_uint64_t mtime;
grub_uint64_t ctime;
grub_uint64_t create_time;
grub_uint32_t atime_sec;
grub_uint32_t mtime_sec;
grub_uint32_t ctime_sec;
grub_uint32_t create_time_sec;
grub_uint32_t gen;
grub_uint32_t kernel_flags;
grub_uint32_t flags;
grub_uint32_t extsz;
grub_uint64_t ext[2];
union
{
struct
{
grub_uint64_t dir_blocks[GRUB_UFS_DIRBLKS];
grub_uint64_t indir_blocks[GRUB_UFS_INDIRBLKS];
} blocks;
grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 8];
};
grub_uint8_t unused[24];
} __attribute__ ((packed));
#else
/* UFS inode. */
struct grub_ufs_inode
{
grub_uint16_t mode;
grub_uint16_t nlinks;
grub_uint16_t uid;
grub_uint16_t gid;
grub_int64_t size;
grub_uint64_t atime;
grub_uint64_t mtime;
grub_uint64_t ctime;
union
{
struct
{
grub_uint32_t dir_blocks[GRUB_UFS_DIRBLKS];
grub_uint32_t indir_blocks[GRUB_UFS_INDIRBLKS];
} blocks;
grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 4];
};
grub_uint32_t flags;
grub_uint32_t nblocks;
grub_uint32_t gen;
grub_uint32_t unused;
grub_uint8_t pad[12];
} __attribute__ ((packed));
#endif
/* Directory entry. */
struct grub_ufs_dirent
{
grub_uint32_t ino;
grub_uint16_t direntlen;
union
{
grub_uint16_t namelen;
struct
{
grub_uint8_t filetype_bsd;
grub_uint8_t namelen_bsd;
};
};
} __attribute__ ((packed));
/* Information about a "mounted" ufs filesystem. */
struct grub_ufs_data
{
struct grub_ufs_sblock sblock;
grub_disk_t disk;
struct grub_ufs_inode inode;
int ino;
int linknest;
};
static grub_dl_t my_mod;
/* Forward declaration. */
static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data,
const char *path);
static grub_disk_addr_t
grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk)
{
struct grub_ufs_sblock *sblock = &data->sblock;
unsigned int indirsz;
int log2_blksz;
/* Direct. */
if (blk < GRUB_UFS_DIRBLKS)
return INODE_DIRBLOCKS (data, blk);
log2_blksz = grub_le_to_cpu32 (data->sblock.log2_blksz);
blk -= GRUB_UFS_DIRBLKS;
indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ;
/* Single indirect block. */
if (blk < indirsz)
{
#ifdef MODE_UFS2
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
#else
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
#endif
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 0) << log2_blksz,
0, sizeof (indir), indir);
return indir[blk];
}
blk -= indirsz;
/* Double indirect block. */
if (blk < indirsz * indirsz)
{
#ifdef MODE_UFS2
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
#else
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
#endif
grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1) << log2_blksz,
0, sizeof (indir), indir);
grub_disk_read (data->disk,
(indir [blk / indirsz])
<< log2_blksz,
0, sizeof (indir), indir);
return indir[blk % indirsz];
}
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ufs does not support triple indirect blocks");
return 0;
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_ufs_read_file (struct grub_ufs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
struct grub_ufs_sblock *sblock = &data->sblock;
int i;
int blockcnt;
/* Adjust len so it we can't read past the end of the file. */
if (len + pos > INODE_SIZE (data))
len = INODE_SIZE (data) - pos;
blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock);
for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++)
{
int blknr;
int blockoff = pos % UFS_BLKSZ (sblock);
int blockend = UFS_BLKSZ (sblock);
int skipfirst = 0;
blknr = grub_ufs_get_file_block (data, i);
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) % UFS_BLKSZ (sblock);
if (!blockend)
blockend = UFS_BLKSZ (sblock);
}
/* First block. */
if (i == (pos / (int) UFS_BLKSZ (sblock)))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
/* XXX: If the block number is 0 this block is not stored on
disk but is zero filled instead. */
if (blknr)
{
data->disk->read_hook = read_hook;
grub_disk_read (data->disk,
blknr << grub_le_to_cpu32 (data->sblock.log2_blksz),
skipfirst, blockend, buf);
data->disk->read_hook = 0;
if (grub_errno)
return -1;
}
else
grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0);
buf += UFS_BLKSZ (sblock) - skipfirst;
}
return len;
}
/* Read inode INO from the mounted filesystem described by DATA. This
inode is used by default now. */
static grub_err_t
grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode)
{
struct grub_ufs_sblock *sblock = &data->sblock;
/* Determine the group the inode is in. */
int group = ino / grub_le_to_cpu32 (sblock->ino_per_group);
/* Determine the inode within the group. */
int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group);
/* The first block of the group. */
int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group));
#ifndef MODE_UFS2
grpblk += grub_le_to_cpu32 (sblock->cylg_offset)
* (group & (~grub_le_to_cpu32 (sblock->cylg_mask)));
#endif
if (!inode)
{
inode = (char *) &data->inode;
data->ino = ino;
}
grub_disk_read (data->disk,
((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk)
<< grub_le_to_cpu32 (data->sblock.log2_blksz))
+ grpino / UFS_INODE_PER_BLOCK,
(grpino % UFS_INODE_PER_BLOCK)
* sizeof (struct grub_ufs_inode),
sizeof (struct grub_ufs_inode),
inode);
return grub_errno;
}
/* Lookup the symlink the current inode points to. INO is the inode
number of the directory the symlink is relative to. */
static grub_err_t
grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
{
char symlink[INODE_SIZE (data)];
if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (INODE_NBLOCKS (data) == 0)
grub_strcpy (symlink, (char *) INODE (data, symlink));
else
{
grub_disk_read (data->disk,
(INODE_DIRBLOCKS (data, 0)
<< grub_le_to_cpu32 (data->sblock.log2_blksz)),
0, INODE_SIZE (data), symlink);
symlink[INODE_SIZE (data)] = '\0';
}
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
ino = GRUB_UFS_INODE;
/* Now load in the old inode. */
if (grub_ufs_read_inode (data, ino, 0))
return grub_errno;
grub_ufs_find_file (data, symlink);
if (grub_errno)
grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
return grub_errno;
}
/* Find the file with the pathname PATH on the filesystem described by
DATA. */
static grub_err_t
grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
{
char fpath[grub_strlen (path) + 1];
char *name = fpath;
char *next;
unsigned int pos = 0;
int dirino;
grub_strcpy (fpath, path);
/* Skip the first slash. */
if (name[0] == '/')
{
name++;
if (!*name)
return 0;
}
/* Extract the actual part from the pathname. */
next = grub_strchr (name, '/');
if (next)
{
next[0] = '\0';
next++;
}
do
{
struct grub_ufs_dirent dirent;
int namelen;
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
(char *) &dirent) < 0)
return grub_errno;
#ifdef MODE_UFS2
namelen = dirent.namelen_bsd;
#else
namelen = grub_le_to_cpu16 (dirent.namelen);
#endif
{
char filename[namelen + 1];
if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
namelen, filename) < 0)
return grub_errno;
filename[namelen] = '\0';
if (!grub_strcmp (name, filename))
{
dirino = data->ino;
grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino), 0);
if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE)
== GRUB_UFS_ATTR_LNK)
{
grub_ufs_lookup_symlink (data, dirino);
if (grub_errno)
return grub_errno;
}
if (!next)
return 0;
pos = 0;
name = next;
next = grub_strchr (name, '/');
if (next)
{
next[0] = '\0';
next++;
}
if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
continue;
}
}
pos += grub_le_to_cpu16 (dirent.direntlen);
} while (pos < INODE_SIZE (data));
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
return grub_errno;
}
/* Mount the filesystem on the disk DISK. */
static struct grub_ufs_data *
grub_ufs_mount (grub_disk_t disk)
{
struct grub_ufs_data *data;
int *sblklist = sblocklist;
data = grub_malloc (sizeof (struct grub_ufs_data));
if (!data)
return 0;
/* Find a UFS sblock. */
while (*sblklist != -1)
{
grub_disk_read (disk, *sblklist, 0, sizeof (struct grub_ufs_sblock),
&data->sblock);
if (grub_errno)
goto fail;
if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC)
{
data->disk = disk;
data->linknest = 0;
return data;
}
sblklist++;
}
fail:
if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE)
{
#ifdef MODE_UFS2
grub_error (GRUB_ERR_BAD_FS, "not an ufs2 filesystem");
#else
grub_error (GRUB_ERR_BAD_FS, "not an ufs1 filesystem");
#endif
}
grub_free (data);
return 0;
}
static grub_err_t
grub_ufs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_ufs_data *data;
unsigned int pos = 0;
data = grub_ufs_mount (device->disk);
if (!data)
return grub_errno;
grub_ufs_read_inode (data, GRUB_UFS_INODE, 0);
if (grub_errno)
return grub_errno;
if (!path || path[0] != '/')
{
grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
return grub_errno;
}
grub_ufs_find_file (data, path);
if (grub_errno)
goto fail;
if ((INODE_MODE (data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR)
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
goto fail;
}
while (pos < INODE_SIZE (data))
{
struct grub_ufs_dirent dirent;
int namelen;
if (grub_ufs_read_file (data, 0, pos, sizeof (dirent),
(char *) &dirent) < 0)
break;
#ifdef MODE_UFS2
namelen = dirent.namelen_bsd;
#else
namelen = grub_le_to_cpu16 (dirent.namelen);
#endif
{
char filename[namelen + 1];
struct grub_dirhook_info info;
struct grub_ufs_inode inode;
grub_memset (&info, 0, sizeof (info));
if (grub_ufs_read_file (data, 0, pos + sizeof (dirent),
namelen, filename) < 0)
break;
filename[namelen] = '\0';
grub_ufs_read_inode (data, dirent.ino, (char *) &inode);
info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE)
== GRUB_UFS_ATTR_DIR);
info.mtime = grub_le_to_cpu64 (inode.mtime);
info.mtimeset = 1;
if (hook (filename, &info))
break;
}
pos += grub_le_to_cpu16 (dirent.direntlen);
}
fail:
grub_free (data);
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_ufs_open (struct grub_file *file, const char *name)
{
struct grub_ufs_data *data;
data = grub_ufs_mount (file->device->disk);
if (!data)
return grub_errno;
grub_ufs_read_inode (data, 2, 0);
if (grub_errno)
{
grub_free (data);
return grub_errno;
}
if (!name || name[0] != '/')
{
grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
return grub_errno;
}
grub_ufs_find_file (data, name);
if (grub_errno)
{
grub_free (data);
return grub_errno;
}
file->data = data;
file->size = INODE_SIZE (data);
return GRUB_ERR_NONE;
}
static grub_ssize_t
grub_ufs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_ufs_data *data =
(struct grub_ufs_data *) file->data;
return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf);
}
static grub_err_t
grub_ufs_close (grub_file_t file)
{
grub_free (file->data);
return GRUB_ERR_NONE;
}
#ifdef MODE_UFS2
static grub_err_t
grub_ufs_label (grub_device_t device, char **label)
{
struct grub_ufs_data *data = 0;
grub_dl_ref (my_mod);
*label = 0;
data = grub_ufs_mount (device->disk);
if (data)
*label = grub_strdup ((char *) data->sblock.volume_name);
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
#endif
static grub_err_t
grub_ufs_uuid (grub_device_t device, char **uuid)
{
struct grub_ufs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_ufs_mount (disk);
if (data && (data->sblock.uuidhi != 0 || data->sblock.uuidlow != 0))
*uuid = grub_xasprintf ("%08x%08x",
(unsigned) grub_le_to_cpu32 (data->sblock.uuidhi),
(unsigned) grub_le_to_cpu32 (data->sblock.uuidlow));
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
/* Get mtime. */
static grub_err_t
grub_ufs_mtime (grub_device_t device, grub_int32_t *tm)
{
struct grub_ufs_data *data = 0;
grub_dl_ref (my_mod);
data = grub_ufs_mount (device->disk);
if (!data)
*tm = 0;
else
#ifdef MODE_UFS2
*tm = grub_le_to_cpu64 (data->sblock.mtime2);
#else
*tm = grub_le_to_cpu32 (data->sblock.mtime);
#endif
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_ufs_fs =
{
#ifdef MODE_UFS2
.name = "ufs2",
#else
.name = "ufs1",
#endif
.dir = grub_ufs_dir,
.open = grub_ufs_open,
.read = grub_ufs_read,
.close = grub_ufs_close,
#ifdef MODE_UFS2
.label = grub_ufs_label,
#endif
.uuid = grub_ufs_uuid,
.mtime = grub_ufs_mtime,
.next = 0
};
#ifdef MODE_UFS2
GRUB_MOD_INIT(ufs2)
#else
GRUB_MOD_INIT(ufs1)
#endif
{
grub_fs_register (&grub_ufs_fs);
my_mod = mod;
}
#ifdef MODE_UFS2
GRUB_MOD_FINI(ufs2)
#else
GRUB_MOD_FINI(ufs1)
#endif
{
grub_fs_unregister (&grub_ufs_fs);
}

3
libr/fs/p/grub/fs/ufs2.c Normal file
View File

@ -0,0 +1,3 @@
/* ufs2.c - Unix File System 2 */
#define MODE_UFS2 1
#include "ufs.c"

826
libr/fs/p/grub/fs/xfs.c Normal file
View File

@ -0,0 +1,826 @@
/* xfs.c - XFS. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#define XFS_INODE_EXTENTS 9
#define XFS_INODE_FORMAT_INO 1
#define XFS_INODE_FORMAT_EXT 2
#define XFS_INODE_FORMAT_BTREE 3
struct grub_xfs_sblock
{
grub_uint8_t magic[4];
grub_uint32_t bsize;
grub_uint8_t unused1[24];
grub_uint16_t uuid[8];
grub_uint8_t unused2[8];
grub_uint64_t rootino;
grub_uint8_t unused3[20];
grub_uint32_t agsize;
grub_uint8_t unused4[20];
grub_uint8_t label[12];
grub_uint8_t log2_bsize;
grub_uint8_t log2_sect;
grub_uint8_t log2_inode;
grub_uint8_t log2_inop;
grub_uint8_t log2_agblk;
grub_uint8_t unused6[67];
grub_uint8_t log2_dirblk;
} __attribute__ ((packed));
struct grub_xfs_dir_header
{
grub_uint8_t count;
grub_uint8_t smallino;
union
{
grub_uint32_t i4;
grub_uint64_t i8;
} parent __attribute__ ((packed));
} __attribute__ ((packed));
struct grub_xfs_dir_entry
{
grub_uint8_t len;
grub_uint16_t offset;
char name[1];
/* Inode number follows, 32 bits. */
} __attribute__ ((packed));
struct grub_xfs_dir2_entry
{
grub_uint64_t inode;
grub_uint8_t len;
} __attribute__ ((packed));
typedef grub_uint32_t grub_xfs_extent[4];
struct grub_xfs_btree_node
{
grub_uint8_t magic[4];
grub_uint16_t level;
grub_uint16_t numrecs;
grub_uint64_t left;
grub_uint64_t right;
grub_uint64_t keys[1];
} __attribute__ ((packed));
struct grub_xfs_btree_root
{
grub_uint16_t level;
grub_uint16_t numrecs;
grub_uint64_t keys[1];
} __attribute__ ((packed));
struct grub_xfs_inode
{
grub_uint8_t magic[2];
grub_uint16_t mode;
grub_uint8_t version;
grub_uint8_t format;
grub_uint8_t unused2[50];
grub_uint64_t size;
grub_uint64_t nblocks;
grub_uint32_t extsize;
grub_uint32_t nextents;
grub_uint8_t unused3[20];
union
{
char raw[156];
struct dir
{
struct grub_xfs_dir_header dirhead;
struct grub_xfs_dir_entry direntry[1];
} dir;
grub_xfs_extent extents[XFS_INODE_EXTENTS];
struct grub_xfs_btree_root btree;
} data __attribute__ ((packed));
} __attribute__ ((packed));
struct grub_xfs_dirblock_tail
{
grub_uint32_t leaf_count;
grub_uint32_t leaf_stale;
} __attribute__ ((packed));
struct grub_fshelp_node
{
struct grub_xfs_data *data;
grub_uint64_t ino;
int inode_read;
struct grub_xfs_inode inode;
};
struct grub_xfs_data
{
struct grub_xfs_sblock sblock;
grub_disk_t disk;
int pos;
int bsize;
int agsize;
struct grub_fshelp_node diropen;
};
static grub_dl_t my_mod;
/* Filetype information as used in inodes. */
#define FILETYPE_INO_MASK 0170000
#define FILETYPE_INO_REG 0100000
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
#define GRUB_XFS_INO_AGBITS(data) \
((data)->sblock.log2_agblk + (data)->sblock.log2_inop)
#define GRUB_XFS_INO_INOINAG(data, ino) \
(grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1))
#define GRUB_XFS_INO_AG(data,ino) \
(grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data))
#define GRUB_XFS_FSB_TO_BLOCK(data, fsb) \
(((fsb) >> (data)->sblock.log2_agblk) * (data)->agsize \
+ ((fsb) & ((1LL << (data)->sblock.log2_agblk) - 1)))
#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \
((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \
| grub_be_to_cpu32 (exts[ex][1]) >> 9)
#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \
((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \
& (0x1ff)) << 43 \
| (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \
| grub_be_to_cpu32 (exts[ex][3]) >> 21)
#define GRUB_XFS_EXTENT_SIZE(exts,ex) \
(grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1))
#define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8)
#define GRUB_XFS_NEXT_DIRENT(pos,len) \
(pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2)
static inline grub_uint64_t
grub_xfs_inode_block (struct grub_xfs_data *data,
grub_uint64_t ino)
{
long long int inoinag = GRUB_XFS_INO_INOINAG (data, ino);
long long ag = GRUB_XFS_INO_AG (data, ino);
long long block;
block = (inoinag >> data->sblock.log2_inop) + ag * data->agsize;
block <<= (data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS);
return block;
}
static inline int
grub_xfs_inode_offset (struct grub_xfs_data *data,
grub_uint64_t ino)
{
int inoag = GRUB_XFS_INO_INOINAG (data, ino);
return ((inoag & ((1 << data->sblock.log2_inop) - 1)) <<
data->sblock.log2_inode);
}
static grub_err_t
grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino,
struct grub_xfs_inode *inode)
{
grub_uint64_t block = grub_xfs_inode_block (data, ino);
int offset = grub_xfs_inode_offset (data, ino);
/* Read the inode. */
if (grub_disk_read (data->disk, block, offset,
1 << data->sblock.log2_inode, inode))
return grub_errno;
if (grub_strncmp ((char *) inode->magic, "IN", 2))
return grub_error (GRUB_ERR_BAD_FS, "not a correct XFS inode");
return 0;
}
static grub_disk_addr_t
grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_xfs_btree_node *leaf = 0;
int ex, nrec;
grub_xfs_extent *exts;
grub_uint64_t ret = 0;
if (node->inode.format == XFS_INODE_FORMAT_BTREE)
{
grub_uint64_t *keys;
leaf = grub_malloc (node->data->sblock.bsize);
if (leaf == 0)
return 0;
nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs);
keys = &node->inode.data.btree.keys[0];
do
{
int i;
for (i = 0; i < nrec; i++)
{
if (fileblock < grub_be_to_cpu64 (keys[i]))
break;
}
/* Sparse block. */
if (i == 0)
{
grub_free (leaf);
return 0;
}
if (grub_disk_read (node->data->disk,
grub_be_to_cpu64 (keys[i - 1 + nrec])
<< (node->data->sblock.log2_bsize
- GRUB_DISK_SECTOR_BITS),
0, node->data->sblock.bsize, leaf))
return 0;
if (grub_strncmp ((char *) leaf->magic, "BMAP", 4))
{
grub_free (leaf);
grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node");
return 0;
}
nrec = grub_be_to_cpu16 (leaf->numrecs);
keys = &leaf->keys[0];
} while (leaf->level);
exts = (grub_xfs_extent *) keys;
}
else if (node->inode.format == XFS_INODE_FORMAT_EXT)
{
nrec = grub_be_to_cpu32 (node->inode.nextents);
exts = &node->inode.data.extents[0];
}
else
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"XFS does not support inode format %d yet",
node->inode.format);
return 0;
}
/* Iterate over each extent to figure out which extent has
the block we are looking for. */
for (ex = 0; ex < nrec; ex++)
{
grub_uint64_t start = GRUB_XFS_EXTENT_BLOCK (exts, ex);
grub_uint64_t offset = GRUB_XFS_EXTENT_OFFSET (exts, ex);
grub_uint64_t size = GRUB_XFS_EXTENT_SIZE (exts, ex);
/* Sparse block. */
if (fileblock < offset)
break;
else if (fileblock < offset + size)
{
ret = (fileblock - offset + start);
break;
}
}
if (leaf)
grub_free (leaf);
return GRUB_XFS_FSB_TO_BLOCK(node->data, ret);
}
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_xfs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_xfs_read_block,
grub_be_to_cpu64 (node->inode.size),
node->data->sblock.log2_bsize
- GRUB_DISK_SECTOR_BITS);
}
static char *
grub_xfs_read_symlink (grub_fshelp_node_t node)
{
int size = grub_be_to_cpu64 (node->inode.size);
switch (node->inode.format)
{
case XFS_INODE_FORMAT_INO:
return grub_strndup (node->inode.data.raw, size);
case XFS_INODE_FORMAT_EXT:
{
char *symlink;
grub_ssize_t numread;
symlink = grub_malloc (size + 1);
if (!symlink)
return 0;
numread = grub_xfs_read_file (node, 0, 0, size, symlink);
if (numread != size)
{
grub_free (symlink);
return 0;
}
symlink[size] = '\0';
return symlink;
}
}
return 0;
}
static enum grub_fshelp_filetype
grub_xfs_mode_to_filetype (grub_uint16_t mode)
{
if ((grub_be_to_cpu16 (mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY)
return GRUB_FSHELP_DIR;
else if ((grub_be_to_cpu16 (mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_SYMLINK)
return GRUB_FSHELP_SYMLINK;
else if ((grub_be_to_cpu16 (mode)
& FILETYPE_INO_MASK) == FILETYPE_INO_REG)
return GRUB_FSHELP_REG;
return GRUB_FSHELP_UNKNOWN;
}
static int
grub_xfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename);
int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename)
{
struct grub_fshelp_node *fdiro;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node)
- sizeof (struct grub_xfs_inode)
+ (1 << diro->data->sblock.log2_inode));
if (!fdiro)
return 0;
/* The inode should be read, otherwise the filetype can
not be determined. */
fdiro->ino = ino;
fdiro->inode_read = 1;
fdiro->data = diro->data;
grub_xfs_read_inode (diro->data, ino, &fdiro->inode);
return hook (filename,
grub_xfs_mode_to_filetype (fdiro->inode.mode),
fdiro);
}
switch (diro->inode.format)
{
case XFS_INODE_FORMAT_INO:
{
struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0];
int smallino = !diro->inode.data.dir.dirhead.smallino;
int i;
grub_uint64_t parent;
/* If small inode numbers are used to pack the direntry, the
parent inode number is small too. */
if (smallino)
{
parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4);
parent = grub_cpu_to_be64 (parent);
/* The header is a bit smaller than usual. */
de = (struct grub_xfs_dir_entry *) ((char *) de - 4);
}
else
{
parent = diro->inode.data.dir.dirhead.parent.i8;
}
/* Synthesize the direntries for `.' and `..'. */
if (call_hook (diro->ino, "."))
return 1;
if (call_hook (parent, ".."))
return 1;
for (i = 0; i < diro->inode.data.dir.dirhead.count; i++)
{
grub_uint64_t ino;
void *inopos = (((char *) de)
+ sizeof (struct grub_xfs_dir_entry)
+ de->len - 1);
char name[de->len + 1];
if (smallino)
{
ino = grub_be_to_cpu32 (*(grub_uint32_t *) inopos);
ino = grub_cpu_to_be64 (ino);
}
else
ino = *(grub_uint64_t *) inopos;
grub_memcpy (name, de->name, de->len);
name[de->len] = '\0';
if (call_hook (ino, name))
return 1;
de = ((struct grub_xfs_dir_entry *)
(((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len
+ ((smallino ? sizeof (grub_uint32_t)
: sizeof (grub_uint64_t))) - 1));
}
break;
}
case XFS_INODE_FORMAT_BTREE:
case XFS_INODE_FORMAT_EXT:
{
grub_ssize_t numread;
char *dirblock;
grub_uint64_t blk;
int dirblk_size, dirblk_log2;
dirblk_log2 = (dir->data->sblock.log2_bsize
+ dir->data->sblock.log2_dirblk);
dirblk_size = 1 << dirblk_log2;
dirblock = grub_malloc (dirblk_size);
if (! dirblock)
return 0;
/* Iterate over every block the directory has. */
for (blk = 0;
blk < (grub_be_to_cpu64 (dir->inode.size)
>> dirblk_log2);
blk++)
{
/* The header is skipped, the first direntry is stored
from byte 16. */
int pos = 16;
int entries;
int tail_start = (dirblk_size
- sizeof (struct grub_xfs_dirblock_tail));
struct grub_xfs_dirblock_tail *tail;
tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start];
numread = grub_xfs_read_file (dir, 0,
blk << dirblk_log2,
dirblk_size, dirblock);
if (numread != dirblk_size)
return 0;
entries = (grub_be_to_cpu32 (tail->leaf_count)
- grub_be_to_cpu32 (tail->leaf_stale));
/* Iterate over all entries within this block. */
while (pos < (dirblk_size
- (int) sizeof (struct grub_xfs_dir2_entry)))
{
struct grub_xfs_dir2_entry *direntry;
grub_uint16_t *freetag;
char *filename;
direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos];
freetag = (grub_uint16_t *) direntry;
if (*freetag == 0XFFFF)
{
grub_uint16_t *skip = (grub_uint16_t *) (freetag + 1);
/* This entry is not used, go to the next one. */
pos += grub_be_to_cpu16 (*skip);
continue;
}
filename = &dirblock[pos + sizeof (*direntry)];
/* The byte after the filename is for the tag, which
is not used by GRUB. So it can be overwritten. */
filename[direntry->len] = '\0';
if (call_hook (direntry->inode, filename))
{
grub_free (dirblock);
return 1;
}
/* Check if last direntry in this block is
reached. */
entries--;
if (!entries)
break;
/* Select the next directory entry. */
pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len);
pos = GRUB_XFS_ROUND_TO_DIRENT (pos);
}
}
grub_free (dirblock);
break;
}
default:
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"XFS does not support inode format %d yet",
diro->inode.format);
}
return 0;
}
static struct grub_xfs_data *
grub_xfs_mount (grub_disk_t disk)
{
struct grub_xfs_data *data = 0;
data = grub_zalloc (sizeof (struct grub_xfs_data));
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, 0, 0,
sizeof (struct grub_xfs_sblock), &data->sblock))
goto fail;
if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4))
{
grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem");
goto fail;
}
data = grub_realloc (data,
sizeof (struct grub_xfs_data)
- sizeof (struct grub_xfs_inode)
+ (1 << data->sblock.log2_inode));
if (! data)
goto fail;
data->diropen.data = data;
data->diropen.ino = data->sblock.rootino;
data->diropen.inode_read = 1;
data->bsize = grub_be_to_cpu32 (data->sblock.bsize);
data->agsize = grub_be_to_cpu32 (data->sblock.agsize);
data->disk = disk;
data->pos = 0;
grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode);
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem");
grub_free (data);
return 0;
}
static grub_err_t
grub_xfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_xfs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_xfs_mount (device->disk);
if (!data)
goto mount_fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_xfs_iterate_dir,
grub_xfs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_xfs_iterate_dir (fdiro, iterate);
fail:
if (fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
mount_fail:
grub_dl_unref (my_mod);
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
grub_xfs_open (struct grub_file *file, const char *name)
{
struct grub_xfs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_xfs_mount (file->device->disk);
if (!data)
goto mount_fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_xfs_iterate_dir,
grub_xfs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
if (!fdiro->inode_read)
{
grub_xfs_read_inode (data, fdiro->ino, &fdiro->inode);
if (grub_errno)
goto fail;
}
if (fdiro != &data->diropen)
grub_memcpy (&data->diropen, fdiro,
sizeof (struct grub_fshelp_node)
- sizeof (struct grub_xfs_inode)
+ (1 << data->sblock.log2_inode));
file->size = grub_be_to_cpu64 (data->diropen.inode.size);
file->data = data;
file->offset = 0;
return 0;
fail:
if (fdiro != &data->diropen)
grub_free (fdiro);
grub_free (data);
mount_fail:
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_xfs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_xfs_data *data =
(struct grub_xfs_data *) file->data;
return grub_xfs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_xfs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_xfs_label (grub_device_t device, char **label)
{
struct grub_xfs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_xfs_mount (disk);
if (data)
*label = grub_strndup ((char *) (data->sblock.label), 12);
else
*label = 0;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static grub_err_t
grub_xfs_uuid (grub_device_t device, char **uuid)
{
struct grub_xfs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_xfs_mount (disk);
if (data)
{
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[0]),
grub_be_to_cpu16 (data->sblock.uuid[1]),
grub_be_to_cpu16 (data->sblock.uuid[2]),
grub_be_to_cpu16 (data->sblock.uuid[3]),
grub_be_to_cpu16 (data->sblock.uuid[4]),
grub_be_to_cpu16 (data->sblock.uuid[5]),
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
}
else
*uuid = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_xfs_fs =
{
.name = "xfs",
.dir = grub_xfs_dir,
.open = grub_xfs_open,
.read = grub_xfs_read,
.close = grub_xfs_close,
.label = grub_xfs_label,
.uuid = grub_xfs_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};
GRUB_MOD_INIT(xfs)
{
grub_fs_register (&grub_xfs_fs);
my_mod = mod;
}
GRUB_MOD_FINI(xfs)
{
grub_fs_unregister (&grub_xfs_fs);
}

2543
libr/fs/p/grub/fs/zfs/zfs.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, Inc.
*
* GRUB is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
void
fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
zio_cksum_t *zcp)
{
const grub_uint64_t *ip = buf;
const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t));
grub_uint64_t a0, b0, a1, b1;
for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2)
{
a0 += grub_zfs_to_cpu64 (ip[0], endian);
a1 += grub_zfs_to_cpu64 (ip[1], endian);
b0 += a0;
b1 += a1;
}
zcp->zc_word[0] = grub_cpu_to_zfs64 (a0, endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 (a1, endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 (b0, endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 (b1, endian);
}
void
fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian,
zio_cksum_t *zcp)
{
const grub_uint32_t *ip = buf;
const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t));
grub_uint64_t a, b, c, d;
for (a = b = c = d = 0; ip < ipend; ip++)
{
a += grub_zfs_to_cpu32 (ip[0], endian);;
b += a;
c += b;
d += c;
}
zcp->zc_word[0] = grub_cpu_to_zfs64 (a, endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 (b, endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 (c, endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 (d, endian);
}

View File

@ -0,0 +1,93 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, Inc.
*
* GRUB is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
#define MATCH_BITS 6
#define MATCH_MIN 3
#define OFFSET_MASK ((1 << (16 - MATCH_BITS)) - 1)
/*
* Decompression Entry - lzjb
*/
#ifndef NBBY
#define NBBY 8
#endif
grub_err_t
lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
grub_size_t d_len);
grub_err_t
lzjb_decompress (void *s_start, void *d_start, grub_size_t s_len,
grub_size_t d_len)
{
grub_uint8_t *src = s_start;
grub_uint8_t *dst = d_start;
grub_uint8_t *d_end = (grub_uint8_t *) d_start + d_len;
grub_uint8_t *s_end = (grub_uint8_t *) s_start + s_len;
grub_uint8_t *cpy, copymap = 0;
int copymask = 1 << (NBBY - 1);
while (dst < d_end && src < s_end)
{
if ((copymask <<= 1) == (1 << NBBY))
{
copymask = 1;
copymap = *src++;
}
if (src >= s_end)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
if (copymap & copymask)
{
int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
src += 2;
cpy = dst - offset;
if (src > s_end || cpy < (grub_uint8_t *) d_start)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
while (--mlen >= 0 && dst < d_end)
*dst++ = *cpy++;
}
else
*dst++ = *src++;
}
if (dst < d_end)
return grub_error (GRUB_ERR_BAD_FS, "lzjb decompression failed");
return GRUB_ERR_NONE;
}

View File

@ -0,0 +1,143 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2007 Sun Microsystems, Inc.
*
* GRUB is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/zfs/zfs.h>
#include <grub/zfs/zio.h>
#include <grub/zfs/dnode.h>
#include <grub/zfs/uberblock_impl.h>
#include <grub/zfs/vdev_impl.h>
#include <grub/zfs/zio_checksum.h>
#include <grub/zfs/zap_impl.h>
#include <grub/zfs/zap_leaf.h>
#include <grub/zfs/zfs_znode.h>
#include <grub/zfs/dmu.h>
#include <grub/zfs/dmu_objset.h>
#include <grub/zfs/dsl_dir.h>
#include <grub/zfs/dsl_dataset.h>
/*
* SHA-256 checksum, as specified in FIPS 180-2, available at:
* http://csrc.nist.gov/cryptval
*
* This is a very compact implementation of SHA-256.
* It is designed to be simple and portable, not to be fast.
*/
/*
* The literal definitions according to FIPS180-2 would be:
*
* Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
* Maj(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
*
* We use logical equivalents which require one less op.
*/
#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
#define Maj(x, y, z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
#define Rot32(x, s) (((x) >> s) | ((x) << (32 - s)))
#define SIGMA0(x) (Rot32(x, 2) ^ Rot32(x, 13) ^ Rot32(x, 22))
#define SIGMA1(x) (Rot32(x, 6) ^ Rot32(x, 11) ^ Rot32(x, 25))
#define sigma0(x) (Rot32(x, 7) ^ Rot32(x, 18) ^ ((x) >> 3))
#define sigma1(x) (Rot32(x, 17) ^ Rot32(x, 19) ^ ((x) >> 10))
static const grub_uint32_t SHA256_K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static void
SHA256Transform(grub_uint32_t *H, const grub_uint8_t *cp)
{
grub_uint32_t a, b, c, d, e, f, g, h, t, T1, T2, W[64];
for (t = 0; t < 16; t++, cp += 4)
W[t] = (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3];
for (t = 16; t < 64; t++)
W[t] = sigma1(W[t - 2]) + W[t - 7] +
sigma0(W[t - 15]) + W[t - 16];
a = H[0]; b = H[1]; c = H[2]; d = H[3];
e = H[4]; f = H[5]; g = H[6]; h = H[7];
for (t = 0; t < 64; t++) {
T1 = h + SIGMA1(e) + Ch(e, f, g) + SHA256_K[t] + W[t];
T2 = SIGMA0(a) + Maj(a, b, c);
h = g; g = f; f = e; e = d + T1;
d = c; c = b; b = a; a = T1 + T2;
}
H[0] += a; H[1] += b; H[2] += c; H[3] += d;
H[4] += e; H[5] += f; H[6] += g; H[7] += h;
}
void
zio_checksum_SHA256(const void *buf, grub_uint64_t size,
grub_zfs_endian_t endian, zio_cksum_t *zcp)
{
grub_uint32_t H[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 };
grub_uint8_t pad[128];
unsigned padsize = size & 63;
unsigned i;
for (i = 0; i < size - padsize; i += 64)
SHA256Transform(H, (grub_uint8_t *)buf + i);
for (i = 0; i < padsize; i++)
pad[i] = ((grub_uint8_t *)buf)[i];
for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++)
pad[padsize] = 0;
for (i = 0; i < 8; i++)
pad[padsize++] = (size << 3) >> (56 - 8 * i);
for (i = 0; i < padsize; i += 64)
SHA256Transform(H, pad + i);
zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1],
endian);
zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3],
endian);
zcp->zc_word[2] = grub_cpu_to_zfs64 ((grub_uint64_t)H[4] << 32 | H[5],
endian);
zcp->zc_word[3] = grub_cpu_to_zfs64 ((grub_uint64_t)H[6] << 32 | H[7],
endian);
}

View File

@ -0,0 +1,412 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2009 Free Software Foundation, Inc.
* Copyright 2008 Sun Microsystems, Inc.
*
* GRUB is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/zfs/zfs.h>
#include <grub/device.h>
#include <grub/file.h>
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/env.h>
static inline void
print_tabs (int n)
{
int i;
for (i = 0; i < n; i++)
grub_printf (" ");
}
static grub_err_t
print_state (char *nvlist, int tab)
{
grub_uint64_t ival;
int isok = 1;
print_tabs (tab);
grub_printf ("State: ");
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival))
{
grub_printf ("removed ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
{
grub_printf ("faulted ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival))
{
grub_printf ("offline ");
isok = 0;
}
if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival))
grub_printf ("degraded ");
if (isok)
grub_printf ("online");
grub_printf ("\n");
return GRUB_ERR_NONE;
}
static grub_err_t
print_vdev_info (char *nvlist, int tab)
{
char *type = 0;
type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
if (!type)
{
print_tabs (tab);
grub_printf ("Incorrect VDEV: no type available\n");
return grub_errno;
}
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
{
char *bootpath = 0;
char *path = 0;
char *devid = 0;
print_tabs (tab);
grub_printf ("Leaf VDEV\n");
print_state (nvlist, tab);
bootpath =
grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH);
print_tabs (tab);
if (!bootpath)
grub_printf ("Bootpath: unavailable\n");
else
grub_printf ("Bootpath: %s\n", bootpath);
path = grub_zfs_nvlist_lookup_string (nvlist, "path");
print_tabs (tab);
if (!path)
grub_printf ("Path: unavailable\n");
else
grub_printf ("Path: %s\n", path);
devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
print_tabs (tab);
if (!devid)
grub_printf ("Devid: unavailable\n");
else
grub_printf ("Devid: %s\n", devid);
grub_free (bootpath);
grub_free (devid);
grub_free (path);
return GRUB_ERR_NONE;
}
if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
{
int nelm, i;
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
(nvlist, ZPOOL_CONFIG_CHILDREN);
print_tabs (tab);
if (nelm <= 0)
{
grub_printf ("Incorrect mirror VDEV\n");
return GRUB_ERR_NONE;
}
grub_printf ("Mirror VDEV with %d children\n", nelm);
print_state (nvlist, tab);
for (i = 0; i < nelm; i++)
{
char *child;
child = grub_zfs_nvlist_lookup_nvlist_array
(nvlist, ZPOOL_CONFIG_CHILDREN, i);
print_tabs (tab);
if (!child)
{
grub_printf ("Mirror VDEV element %d isn't correct\n", i);
continue;
}
grub_printf ("Mirror VDEV element %d:\n", i);
print_vdev_info (child, tab + 1);
grub_free (child);
}
}
print_tabs (tab);
grub_printf ("Unknown VDEV type: %s\n", type);
return GRUB_ERR_NONE;
}
static grub_err_t
get_bootpath (char *nvlist, char **bootpath, char **devid)
{
char *type = 0;
type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE);
if (!type)
return grub_errno;
if (grub_strcmp (type, VDEV_TYPE_DISK) == 0)
{
*bootpath = grub_zfs_nvlist_lookup_string (nvlist,
ZPOOL_CONFIG_PHYS_PATH);
*devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID);
if (!*bootpath || !*devid)
{
grub_free (*bootpath);
grub_free (*devid);
*bootpath = 0;
*devid = 0;
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0)
{
int nelm, i;
nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm
(nvlist, ZPOOL_CONFIG_CHILDREN);
for (i = 0; i < nelm; i++)
{
char *child;
child = grub_zfs_nvlist_lookup_nvlist_array (nvlist,
ZPOOL_CONFIG_CHILDREN,
i);
get_bootpath (child, bootpath, devid);
grub_free (child);
if (*bootpath && *devid)
return GRUB_ERR_NONE;
}
}
return GRUB_ERR_NONE;
}
static char *poolstates[] = {
[POOL_STATE_ACTIVE] = "active",
[POOL_STATE_EXPORTED] = "exported",
[POOL_STATE_DESTROYED] = "destroyed",
[POOL_STATE_SPARE] = "reserved for hot spare",
[POOL_STATE_L2CACHE] = "level 2 ARC device",
[POOL_STATE_UNINITIALIZED] = "uninitialized",
[POOL_STATE_UNAVAIL] = "unavailable",
[POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active"
};
static grub_err_t
grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc,
char **args)
{
grub_device_t dev;
char *devname;
grub_err_t err;
char *nvlist = 0;
char *nv = 0;
char *poolname;
grub_uint64_t guid;
grub_uint64_t pool_state;
int found;
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
{
devname = grub_strdup (args[0] + 1);
if (devname)
devname[grub_strlen (devname) - 1] = 0;
}
else
devname = grub_strdup (args[0]);
if (!devname)
return grub_errno;
dev = grub_device_open (devname);
grub_free (devname);
if (!dev)
return grub_errno;
err = grub_zfs_fetch_nvlist (dev, &nvlist);
grub_device_close (dev);
if (err)
return err;
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
if (!poolname)
grub_printf ("Pool name: unavailable\n");
else
grub_printf ("Pool name: %s\n", poolname);
found =
grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid);
if (!found)
grub_printf ("Pool GUID: unavailable\n");
else
grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid);
found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE,
&pool_state);
if (!found)
grub_printf ("Unable to retrieve pool state\n");
else if (pool_state >= ARRAY_SIZE (poolstates))
grub_printf ("Unrecognized pool state\n");
else
grub_printf ("Pool state: %s\n", poolstates[pool_state]);
nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
if (!nv)
grub_printf ("No vdev tree available\n");
else
print_vdev_info (nv, 1);
grub_free (nv);
grub_free (nvlist);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc,
char **args)
{
grub_device_t dev;
char *devname;
grub_err_t err;
char *nvlist = 0;
char *nv = 0;
char *bootpath = 0, *devid = 0;
char *fsname;
char *bootfs;
char *poolname;
grub_uint64_t mdnobj;
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required");
devname = grub_file_get_device_name (args[0]);
if (grub_errno)
return grub_errno;
dev = grub_device_open (devname);
grub_free (devname);
if (!dev)
return grub_errno;
err = grub_zfs_fetch_nvlist (dev, &nvlist);
fsname = grub_strchr (args[0], ')');
if (fsname)
fsname++;
else
fsname = args[0];
if (!err)
err = grub_zfs_getmdnobj (dev, fsname, &mdnobj);
grub_device_close (dev);
if (err)
return err;
poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
if (!poolname)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_FS, "No poolname found");
return grub_errno;
}
nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE);
if (nv)
get_bootpath (nv, &bootpath, &devid);
grub_free (nv);
grub_free (nvlist);
if (bootpath && devid)
{
bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu bootpath=%s diskdevid=%s",
poolname, (unsigned long long) mdnobj,
bootpath, devid);
if (!bootfs)
return grub_errno;
}
else
{
bootfs = grub_xasprintf ("zfs-bootfs=%s/%llu",
poolname, (unsigned long long) mdnobj);
if (!bootfs)
return grub_errno;
}
if (argc >= 2)
grub_env_set (args[1], bootfs);
else
grub_printf ("%s\n", bootfs);
grub_free (bootfs);
grub_free (poolname);
grub_free (bootpath);
grub_free (devid);
return GRUB_ERR_NONE;
}
static grub_command_t cmd_info, cmd_bootfs;
GRUB_MOD_INIT (zfsinfo)
{
cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
"zfsinfo DEVICE",
"Print ZFS info about DEVICE.");
cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
"zfs-bootfs FILESYSTEM [VARIABLE]",
"Print ZFS-BOOTFSOBJ or set it to VARIABLE");
}
GRUB_MOD_FINI (zfsinfo)
{
grub_unregister_command (cmd_info);
grub_unregister_command (cmd_bootfs);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
#ifndef _FOO_
#define _FOO_
#include <config-util.h>
#define GRUB_UTIL
#define SIZEOF_VOID_P 4
#define SIZEOF_LONG 4
#define GRUB_FILE "/tmp/"
#define NESTED_FUNC_ATTR
#undef WORDS_BIGENDIAN
//#define Elf_Sym void
#define grub_cpu_idle() //
#define grub_dl_ref(x) //
#define grub_dl_unref(x) //
#define grub_dl_unload_unneeded(x) //
#define grub_malloc(x) malloc(x)
#define grub_realloc(x,y) realloc(x,y)
#define grub_free(x) free(x)
#define grub_zalloc(x) calloc(1,x)
#include <stdlib.h>
#endif

Binary file not shown.

View File

@ -0,0 +1,128 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)exec.h 8.1 (Berkeley) 6/11/93
* $FreeBSD$
*/
#ifndef GRUB_AOUT_HEADER
#define GRUB_AOUT_HEADER 1
#include <grub/types.h>
struct grub_aout32_header
{
grub_uint32_t a_midmag; /* htonl(flags<<26 | mid<<16 | magic) */
grub_uint32_t a_text; /* text segment size */
grub_uint32_t a_data; /* initialized data size */
grub_uint32_t a_bss; /* uninitialized data size */
grub_uint32_t a_syms; /* symbol table size */
grub_uint32_t a_entry; /* entry point */
grub_uint32_t a_trsize; /* text relocation size */
grub_uint32_t a_drsize; /* data relocation size */
};
struct grub_aout64_header
{
grub_uint32_t a_midmag; /* htonl(flags<<26 | mid<<16 | magic) */
grub_uint64_t a_text; /* text segment size */
grub_uint64_t a_data; /* initialized data size */
grub_uint64_t a_bss; /* uninitialized data size */
grub_uint64_t a_syms; /* symbol table size */
grub_uint64_t a_entry; /* entry point */
grub_uint64_t a_trsize; /* text relocation size */
grub_uint64_t a_drsize; /* data relocation size */
};
union grub_aout_header
{
struct grub_aout32_header aout32;
struct grub_aout64_header aout64;
};
#define AOUT_TYPE_NONE 0
#define AOUT_TYPE_AOUT32 1
#define AOUT_TYPE_AOUT64 6
#define AOUT32_OMAGIC 0x107 /* 0407 old impure format */
#define AOUT32_NMAGIC 0x108 /* 0410 read-only text */
#define AOUT32_ZMAGIC 0x10b /* 0413 demand load format */
#define AOUT32_QMAGIC 0xcc /* 0314 "compact" demand load format */
#define AOUT64_OMAGIC 0x1001
#define AOUT64_ZMAGIC 0x1002
#define AOUT64_NMAGIC 0x1003
#define AOUT_MID_ZERO 0 /* unknown - implementation dependent */
#define AOUT_MID_SUN010 1 /* sun 68010/68020 binary */
#define AOUT_MID_SUN020 2 /* sun 68020-only binary */
#define AOUT_MID_I386 134 /* i386 BSD binary */
#define AOUT_MID_SPARC 138 /* sparc */
#define AOUT_MID_HP200 200 /* hp200 (68010) BSD binary */
#define AOUT_MID_SUN 0x103
#define AOUT_MID_HP300 300 /* hp300 (68020+68881) BSD binary */
#define AOUT_MID_HPUX 0x20C /* hp200/300 HP-UX binary */
#define AOUT_MID_HPUX800 0x20B /* hp800 HP-UX binary */
#define AOUT_FLAG_PIC 0x10 /* contains position independent code */
#define AOUT_FLAG_DYNAMIC 0x20 /* contains run-time link-edit info */
#define AOUT_FLAG_DPMASK 0x30 /* mask for the above */
#define AOUT_GETMAGIC(header) ((header).a_midmag & 0xffff)
#define AOUT_GETMID(header) ((header).a_midmag >> 16) & 0x03ff)
#define AOUT_GETFLAG(header) ((header).a_midmag >> 26) & 0x3f)
#ifndef GRUB_UTIL
int EXPORT_FUNC(grub_aout_get_type) (union grub_aout_header *header);
grub_err_t EXPORT_FUNC(grub_aout_load) (grub_file_t file, int offset,
void *load_addr, int load_size,
grub_size_t bss_size);
#endif
#endif /* ! GRUB_AOUT_HEADER */

View File

@ -0,0 +1,91 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2004,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_BSDLABEL_PARTITION_HEADER
#define GRUB_BSDLABEL_PARTITION_HEADER 1
/* Constants for BSD disk label. */
#define GRUB_PC_PARTITION_BSD_LABEL_SECTOR 1
#define GRUB_PC_PARTITION_BSD_LABEL_MAGIC 0x82564557
/* BSD partition types. */
#define GRUB_PC_PARTITION_BSD_TYPE_UNUSED 0
#define GRUB_PC_PARTITION_BSD_TYPE_SWAP 1
#define GRUB_PC_PARTITION_BSD_TYPE_V6 2
#define GRUB_PC_PARTITION_BSD_TYPE_V7 3
#define GRUB_PC_PARTITION_BSD_TYPE_SYSV 4
#define GRUB_PC_PARTITION_BSD_TYPE_V71K 5
#define GRUB_PC_PARTITION_BSD_TYPE_V8 6
#define GRUB_PC_PARTITION_BSD_TYPE_BSDFFS 7
#define GRUB_PC_PARTITION_BSD_TYPE_MSDOS 8
#define GRUB_PC_PARTITION_BSD_TYPE_BSDLFS 9
#define GRUB_PC_PARTITION_BSD_TYPE_OTHER 10
#define GRUB_PC_PARTITION_BSD_TYPE_HPFS 11
#define GRUB_PC_PARTITION_BSD_TYPE_ISO9660 12
#define GRUB_PC_PARTITION_BSD_TYPE_BOOT 13
/* FreeBSD-specific types. */
#define GRUB_PC_PARTITION_FREEBSD_TYPE_VINUM 14
#define GRUB_PC_PARTITION_FREEBSD_TYPE_RAID 15
#define GRUB_PC_PARTITION_FREEBSD_TYPE_JFS2 21
/* NetBSD-specific types. */
#define GRUB_PC_PARTITION_NETBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_NETBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_NETBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_NETBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_NETBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_NETBSD_TYPE_RAID 19
#define GRUB_PC_PARTITION_NETBSD_TYPE_CCD 20
#define GRUB_PC_PARTITION_NETBSD_TYPE_JFS2 21
#define GRUB_PC_PARTITION_NETBSD_TYPE_APPLEUFS 22
/* OpenBSD-specific types. */
#define GRUB_PC_PARTITION_OPENBSD_TYPE_ADOS 14
#define GRUB_PC_PARTITION_OPENBSD_TYPE_HFS 15
#define GRUB_PC_PARTITION_OPENBSD_TYPE_FILECORE 16
#define GRUB_PC_PARTITION_OPENBSD_TYPE_EXT2FS 17
#define GRUB_PC_PARTITION_OPENBSD_TYPE_NTFS 18
#define GRUB_PC_PARTITION_OPENBSD_TYPE_RAID 19
#define GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION 2
/* The BSD partition entry. */
struct grub_partition_bsd_entry
{
grub_uint32_t size;
grub_uint32_t offset;
grub_uint32_t fragment_size;
grub_uint8_t fs_type;
grub_uint8_t fs_fragments;
grub_uint16_t fs_cylinders;
} __attribute__ ((packed));
/* The BSD disk label. Only define members useful for GRUB. */
struct grub_partition_bsd_disk_label
{
grub_uint32_t magic;
grub_uint8_t padding[128];
grub_uint32_t magic2;
grub_uint16_t checksum;
grub_uint16_t num_partitions;
grub_uint32_t boot_size;
grub_uint32_t superblock_size;
} __attribute__ ((packed));
#endif /* ! GRUB_PC_PARTITION_HEADER */

View File

@ -0,0 +1,28 @@
/* bufio.h - prototypes for bufio */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_BUFIO_H
#define GRUB_BUFIO_H 1
#include <grub/file.h>
grub_file_t EXPORT_FUNC (grub_bufio_open) (grub_file_t io, int size);
grub_file_t EXPORT_FUNC (grub_buffile_open) (const char *name, int size);
#endif /* ! GRUB_BUFIO_H */

View File

@ -0,0 +1,134 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_CHARSET_HEADER
#define GRUB_CHARSET_HEADER 1
#include <grub/types.h>
#define GRUB_UINT8_1_LEADINGBIT 0x80
#define GRUB_UINT8_2_LEADINGBITS 0xc0
#define GRUB_UINT8_3_LEADINGBITS 0xe0
#define GRUB_UINT8_4_LEADINGBITS 0xf0
#define GRUB_UINT8_5_LEADINGBITS 0xf8
#define GRUB_UINT8_6_LEADINGBITS 0xfc
#define GRUB_UINT8_7_LEADINGBITS 0xfe
#define GRUB_UINT8_1_TRAILINGBIT 0x01
#define GRUB_UINT8_2_TRAILINGBITS 0x03
#define GRUB_UINT8_3_TRAILINGBITS 0x07
#define GRUB_UINT8_4_TRAILINGBITS 0x0f
#define GRUB_UINT8_5_TRAILINGBITS 0x1f
#define GRUB_UINT8_6_TRAILINGBITS 0x3f
#define GRUB_UCS2_LIMIT 0x10000
#define GRUB_UTF16_UPPER_SURROGATE(code) \
(0xD800 + ((((code) - GRUB_UCS2_LIMIT) >> 12) & 0xfff))
#define GRUB_UTF16_LOWER_SURROGATE(code) \
(0xDC00 + (((code) - GRUB_UCS2_LIMIT) & 0xfff))
grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend);
/* Convert UTF-16 to UTF-8. */
static inline grub_uint8_t *
grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
grub_size_t size)
{
grub_uint32_t code_high = 0;
while (size--)
{
grub_uint32_t code = *src++;
if (code_high)
{
if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Surrogate pair. */
code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
*dest++ = (code >> 18) | 0xF0;
*dest++ = ((code >> 12) & 0x3F) | 0x80;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
else
{
/* Error... */
*dest++ = '?';
}
code_high = 0;
}
else
{
if (code <= 0x007F)
*dest++ = code;
else if (code <= 0x07FF)
{
*dest++ = (code >> 6) | 0xC0;
*dest++ = (code & 0x3F) | 0x80;
}
else if (code >= 0xD800 && code <= 0xDBFF)
{
code_high = code;
continue;
}
else if (code >= 0xDC00 && code <= 0xDFFF)
{
/* Error... */
*dest++ = '?';
}
else if (code < 0x10000)
{
*dest++ = (code >> 12) | 0xE0;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
else
{
*dest++ = (code >> 18) | 0xF0;
*dest++ = ((code >> 12) & 0x3F) | 0x80;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
}
}
return dest;
}
/* Convert UCS-4 to UTF-8. */
char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size);
int
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize);
int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position);
void
grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size,
grub_uint8_t *dest, grub_size_t destsize);
grub_size_t grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend);
#endif

View File

@ -0,0 +1,123 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_COMMAND_HEADER
#define GRUB_COMMAND_HEADER 1
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/list.h>
typedef enum grub_command_flags
{
/* This is an extended command. */
GRUB_COMMAND_FLAG_EXTCMD = 0x10,
/* This is an dynamic command. */
GRUB_COMMAND_FLAG_DYNCMD = 0x20,
/* This command accepts block arguments. */
GRUB_COMMAND_FLAG_BLOCKS = 0x40,
/* This command accepts unknown arguments as direct parameters. */
GRUB_COMMAND_ACCEPT_DASH = 0x80,
/* This command accepts only options preceding direct arguments. */
GRUB_COMMAND_OPTIONS_AT_START = 0x100,
/* Can be executed in an entries extractor. */
GRUB_COMMAND_FLAG_EXTRACTOR = 0x200
} grub_command_flags_t;
struct grub_command;
typedef grub_err_t (*grub_command_func_t) (struct grub_command *cmd,
int argc, char **argv);
/* The command description. */
struct grub_command
{
/* The next element. */
struct grub_command *next;
/* The name. */
const char *name;
/* The priority. */
int prio;
/* The callback function. */
grub_command_func_t func;
/* The flags. */
grub_command_flags_t flags;
/* The summary of the command usage. */
const char *summary;
/* The description of the command. */
const char *description;
/* Arbitrary data. */
void *data;
};
typedef struct grub_command *grub_command_t;
extern grub_command_t EXPORT_VAR(grub_command_list);
grub_command_t
EXPORT_FUNC(grub_register_command_prio) (const char *name,
grub_command_func_t func,
const char *summary,
const char *description,
int prio);
void EXPORT_FUNC(grub_unregister_command) (grub_command_t cmd);
static inline grub_command_t
grub_register_command (const char *name,
grub_command_func_t func,
const char *summary,
const char *description)
{
return grub_register_command_prio (name, func, summary, description, 0);
}
static inline grub_command_t
grub_register_command_p1 (const char *name,
grub_command_func_t func,
const char *summary,
const char *description)
{
return grub_register_command_prio (name, func, summary, description, 1);
}
static inline grub_command_t
grub_command_find (const char *name)
{
return grub_named_list_find (GRUB_AS_NAMED_LIST (grub_command_list), name);
}
static inline grub_err_t
grub_command_execute (const char *name, int argc, char **argv)
{
grub_command_t cmd;
cmd = grub_command_find (name);
return (cmd) ? cmd->func (cmd, argc, argv) : GRUB_ERR_FILE_NOT_FOUND;
}
#define FOR_COMMANDS(var) FOR_LIST_ELEMENTS((var), grub_command_list)
void grub_register_core_commands (void);
#endif /* ! GRUB_COMMAND_HEADER */

View File

@ -0,0 +1 @@
../../include/grub/i386

View File

View File

View File

@ -0,0 +1,190 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_CS5536_HEADER
#define GRUB_CS5536_HEADER 1
#ifndef ASM_FILE
#include <grub/pci.h>
#include <grub/err.h>
#include <grub/smbus.h>
#endif
#define GRUB_CS5536_PCIID 0x208f1022
#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4
#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8
#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc
#define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008
#define GRUB_CS5536_MSR_SMB_BAR 0x8000000b
#define GRUB_CS5536_SMBUS_REGS_SIZE 8
#define GRUB_CS5536_GPIO_REGS_SIZE 256
#define GRUB_CS5536_MFGPT_REGS_SIZE 64
#define GRUB_CS5536_IRQ_MAP_REGS_SIZE 32
#define GRUB_CS5536_PM_REGS_SIZE 128
#define GRUB_CS5536_ACPI_REGS_SIZE 32
#define GRUB_CS5536_USB_OPTION_REGS_SIZE 0x1c
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX 1
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK 0x03
#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC 0x02
#define GRUB_CS5536_DESTINATION_GLIU 0
#define GRUB_CS5536_DESTINATION_GLPCI_SB 1
#define GRUB_CS5536_DESTINATION_USB 2
#define GRUB_CS5536_DESTINATION_IDE 3
#define GRUB_CS5536_DESTINATION_DD 4
#define GRUB_CS5536_DESTINATION_ACC 5
#define GRUB_CS5536_DESTINATION_GLCP 7
#define GRUB_CS5536_P2D_DEST_SHIFT 61
#define GRUB_CS5536_P2D_LOG_ALIGN 12
#define GRUB_CS5536_P2D_ALIGN (1 << GRUB_CS5536_P2D_LOG_ALIGN)
#define GRUB_CS5536_P2D_BASE_SHIFT 20
#define GRUB_CS5536_P2D_MASK_SHIFT 0
#define GRUB_CS5536_MSR_GL_IOD_START 0x000100e0
#define GRUB_CS5536_IOD_DEST_SHIFT 61
#define GRUB_CS5536_IOD_BASE_SHIFT 20
#define GRUB_CS5536_IOD_MASK_SHIFT 0
#define GRUB_CS5536_IOD_ADDR_MASK 0xfffff
#define GRUB_CS5536_MSR_GPIO_BAR 0x8000000c
#define GRUB_CS5536_MSR_MFGPT_BAR 0x8000000d
#define GRUB_CS5536_MSR_ACPI_BAR 0x8000000e
#define GRUB_CS5536_MSR_PM_BAR 0x8000000f
#define GRUB_CS5536_MSR_DIVIL_LEG_IO 0x80000014
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 0x00000001
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000
#define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024
#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025
#define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e
#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80
#define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008
#define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009
#define GRUB_CS5536_MSR_USB_CONTROLLER_BASE 0x4000000a
#define GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE 0x4000000b
#define GRUB_CS5536_MSR_USB_BASE_ADDR_MASK 0x00ffffff00ULL
#define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x0400000000ULL
#define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x0200000000ULL
#define GRUB_CS5536_MSR_USB_BASE_PME_ENABLED 0x0800000000ULL
#define GRUB_CS5536_MSR_USB_BASE_PME_STATUS 0x1000000000ULL
#define GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT 40
#define GRUB_CS5536_MSR_IDE_IO_BAR 0x60000008
#define GRUB_CS5536_MSR_IDE_IO_BAR_UNITS 1
#define GRUB_CS5536_MSR_IDE_IO_BAR_ADDR_MASK 0xfffffff0
#define GRUB_CS5536_MSR_IDE_CFG 0x60000010
#define GRUB_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE 2
#define GRUB_CS5536_MSR_IDE_TIMING 0x60000012
#define GRUB_CS5536_MSR_IDE_TIMING_PIO0 0x98
#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT 24
#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT 16
#define GRUB_CS5536_MSR_IDE_CAS_TIMING 0x60000013
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0 0x99
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT 24
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT 6
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT 4
#define GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 2
#define GRUB_CS5536_MSR_GL_PCI_CTRL 0x00000010
#define GRUB_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE 1
#define GRUB_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE 2
#define GRUB_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT 35
#define GRUB_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT 60
#define GRUB_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT 56
#define GRUB_CS5536_MSR_GL_REGIONS_START 0x00000020
#define GRUB_CS5536_MSR_GL_REGIONS_NUM 16
#define GRUB_CS5536_MSR_GL_REGION_ENABLE 1
#define GRUB_CS5536_MSR_GL_REGION_IO 0x100000000ULL
#define GRUB_CS5536_MSR_GL_REGION_BASE_MASK 0xfffff000ULL
#define GRUB_CS5536_MSR_GL_REGION_IO_BASE_SHIFT 12
#define GRUB_CS5536_MSR_GL_REGION_TOP_MASK 0xfffff00000000000ULL
#define GRUB_CS5536_MSR_GL_REGION_IO_TOP_SHIFT 44
#define GRUB_CS5536_MSR_GL_P2D_START 0x00010020
#define GRUB_CS5536_SMB_REG_DATA 0x0
#define GRUB_CS5536_SMB_REG_STATUS 0x1
#define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6)
#define GRUB_CS5536_SMB_REG_STATUS_BER (1 << 5)
#define GRUB_CS5536_SMB_REG_STATUS_NACK (1 << 4)
#define GRUB_CS5536_SMB_REG_CTRL1 0x3
#define GRUB_CS5536_SMB_REG_CTRL1_START 0x01
#define GRUB_CS5536_SMB_REG_CTRL1_STOP 0x02
#define GRUB_CS5536_SMB_REG_CTRL1_ACK 0x10
#define GRUB_CS5536_SMB_REG_ADDR 0x4
#define GRUB_CS5536_SMB_REG_ADDR_MASTER 0x0
#define GRUB_CS5536_SMB_REG_CTRL2 0x5
#define GRUB_CS5536_SMB_REG_CTRL2_ENABLE 0x1
#define GRUB_CS5536_SMB_REG_CTRL3 0x6
#ifdef ASM_FILE
#define GRUB_ULL(x) x
#else
#define GRUB_ULL(x) x ## ULL
#endif
#define GRUB_CS5536_LBAR_ADDR_MASK GRUB_ULL (0x000000000000fff8)
#define GRUB_CS5536_LBAR_ENABLE GRUB_ULL (0x0000000100000000)
#define GRUB_CS5536_LBAR_MASK_MASK GRUB_ULL (0x0000f00000000000)
#define GRUB_CS5536_LBAR_TURN_ON (GRUB_CS5536_LBAR_ENABLE | GRUB_CS5536_LBAR_MASK_MASK)
/* PMON-compatible LBARs. */
#define GRUB_CS5536_LBAR_GPIO 0xb000
#define GRUB_CS5536_LBAR_ACC 0xb200
#define GRUB_CS5536_LBAR_PM 0xb280
#define GRUB_CS5536_LBAR_MFGPT 0xb300
#define GRUB_CS5536_LBAR_ACPI 0xb340
#define GRUB_CS5536_LBAR_IRQ_MAP 0xb360
#define GRUB_CS5536_LBAR_IDE 0xb380
#define GRUB_CS5536_LBAR_SMBUS 0xb390
#define GRUB_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15))
#define GRUB_GPIO_REG_OUT_EN 0x4
#define GRUB_GPIO_REG_OUT_AUX1 0x10
#define GRUB_GPIO_REG_IN_EN 0x20
#define GRUB_GPIO_REG_IN_AUX1 0x34
#ifndef ASM_FILE
int EXPORT_FUNC (grub_cs5536_find) (grub_pci_device_t *devp);
grub_uint64_t EXPORT_FUNC (grub_cs5536_read_msr) (grub_pci_device_t dev,
grub_uint32_t addr);
void EXPORT_FUNC (grub_cs5536_write_msr) (grub_pci_device_t dev,
grub_uint32_t addr,
grub_uint64_t val);
grub_err_t grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev,
grub_uint8_t addr, grub_uint8_t *res);
grub_err_t EXPORT_FUNC (grub_cs5536_read_spd) (grub_port_t smbbase,
grub_uint8_t dev,
struct grub_smbus_spd *res);
grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase);
grub_err_t EXPORT_FUNC (grub_cs5536_init_smbus) (grub_pci_device_t dev,
grub_uint16_t divisor,
grub_port_t *smbbase);
void grub_cs5536_init_geode (grub_pci_device_t dev);
#endif
#endif

View File

@ -0,0 +1,55 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KERNEL_DATETIME_HEADER
#define KERNEL_DATETIME_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
struct grub_datetime
{
grub_uint16_t year;
grub_uint8_t month;
grub_uint8_t day;
grub_uint8_t hour;
grub_uint8_t minute;
grub_uint8_t second;
};
/* Return date and time. */
#ifdef GRUB_MACHINE_EMU
grub_err_t EXPORT_FUNC(grub_get_datetime) (struct grub_datetime *datetime);
/* Set date and time. */
grub_err_t EXPORT_FUNC(grub_set_datetime) (struct grub_datetime *datetime);
#else
grub_err_t grub_get_datetime (struct grub_datetime *datetime);
/* Set date and time. */
grub_err_t grub_set_datetime (struct grub_datetime *datetime);
#endif
int grub_get_weekday (struct grub_datetime *datetime);
char *grub_get_weekday_name (struct grub_datetime *datetime);
void grub_unixtime2datetime (grub_int32_t nix,
struct grub_datetime *datetime);
#endif /* ! KERNEL_DATETIME_HEADER */

View File

@ -0,0 +1,34 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_DECOMPRESSOR_HEADER
#define GRUB_DECOMPRESSOR_HEADER 1
void
grub_decompress_core (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize);
void
find_scratch (void *src, void *dst, unsigned long srcsize,
unsigned long dstsize);
#define GRUB_DECOMPRESSOR_DICT_SIZE (1 << 16)
extern void *grub_decompressor_scratch;
#endif

View File

@ -0,0 +1,41 @@
/* device.h - device manager */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_DEVICE_HEADER
#define GRUB_DEVICE_HEADER 1
#include <grub/symbol.h>
#include <grub/err.h>
struct grub_disk;
struct grub_net;
struct grub_fs;
struct grub_device
{
struct grub_disk *disk;
struct grub_net *net;
};
typedef struct grub_device *grub_device_t;
grub_device_t EXPORT_FUNC(grub_device_open) (const char *name);
grub_err_t EXPORT_FUNC(grub_device_close) (grub_device_t device);
int EXPORT_FUNC(grub_device_iterate) (int (*hook) (const char *name));
#endif /* ! GRUB_DEVICE_HEADER */

View File

@ -0,0 +1,189 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_DISK_HEADER
#define GRUB_DISK_HEADER 1
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
#include <grub/device.h>
/* These are used to set a device id. When you add a new disk device,
you must define a new id for it here. */
enum grub_disk_dev_id
{
GRUB_DISK_DEVICE_BIOSDISK_ID,
GRUB_DISK_DEVICE_OFDISK_ID,
GRUB_DISK_DEVICE_LOOPBACK_ID,
GRUB_DISK_DEVICE_EFIDISK_ID,
GRUB_DISK_DEVICE_RAID_ID,
GRUB_DISK_DEVICE_LVM_ID,
GRUB_DISK_DEVICE_HOST_ID,
GRUB_DISK_DEVICE_ATA_ID,
GRUB_DISK_DEVICE_MEMDISK_ID,
GRUB_DISK_DEVICE_NAND_ID,
GRUB_DISK_DEVICE_UUID_ID,
GRUB_DISK_DEVICE_PXE_ID,
GRUB_DISK_DEVICE_SCSI_ID,
GRUB_DISK_DEVICE_FILE_ID,
GRUB_DISK_DEVICE_LUKS_ID
};
struct grub_disk;
#ifdef GRUB_UTIL
struct grub_disk_memberlist;
#endif
/* Disk device. */
struct grub_disk_dev
{
/* The device name. */
const char *name;
/* The device id used by the cache manager. */
enum grub_disk_dev_id id;
/* Call HOOK with each device name, until HOOK returns non-zero. */
int (*iterate) (int (*hook) (const char *name));
/* Open the device named NAME, and set up DISK. */
grub_err_t (*open) (const char *name, struct grub_disk *disk);
/* Close the disk DISK. */
void (*close) (struct grub_disk *disk);
/* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF. */
grub_err_t (*read) (struct grub_disk *disk, grub_disk_addr_t sector,
grub_size_t size, char *buf);
/* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK. */
grub_err_t (*write) (struct grub_disk *disk, grub_disk_addr_t sector,
grub_size_t size, const char *buf);
#ifdef GRUB_UTIL
struct grub_disk_memberlist *(*memberlist) (struct grub_disk *disk);
const char * (*raidname) (struct grub_disk *disk);
#endif
/* The next disk device. */
struct grub_disk_dev *next;
};
typedef struct grub_disk_dev *grub_disk_dev_t;
struct grub_partition;
/* Disk. */
struct grub_disk
{
/* The disk name. */
const char *name;
/* The underlying disk device. */
grub_disk_dev_t dev;
/* The total number of sectors. */
grub_uint64_t total_sectors;
/* The id used by the disk cache manager. */
unsigned long id;
/* The partition information. This is machine-specific. */
struct grub_partition *partition;
/* Called when a sector was read. OFFSET is between 0 and
the sector size minus 1, and LENGTH is between 0 and the sector size. */
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length);
/* Device-specific data. */
void *data;
};
typedef struct grub_disk *grub_disk_t;
#ifdef GRUB_UTIL
struct grub_disk_memberlist
{
grub_disk_t disk;
struct grub_disk_memberlist *next;
};
typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
#endif
/* The sector size. */
#define GRUB_DISK_SECTOR_SIZE 0x200
#define GRUB_DISK_SECTOR_BITS 9
/* The maximum number of disk caches. */
#define GRUB_DISK_CACHE_NUM 1021
/* The size of a disk cache in sector units. */
#define GRUB_DISK_CACHE_SIZE 8
#define GRUB_DISK_CACHE_BITS 3
/* Return value of grub_disk_get_size() in case disk size is unknown. */
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
/* This is called from the memory manager. */
void grub_disk_cache_invalidate_all (void);
void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev);
void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev);
int EXPORT_FUNC(grub_disk_dev_iterate) (int (*hook) (const char *name));
grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name);
void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk);
grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,
grub_size_t size,
void *buf);
grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk,
grub_disk_addr_t sector,
grub_off_t offset,
grub_size_t size,
const void *buf);
grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void);
extern int EXPORT_VAR(grub_disk_firmware_is_tainted);
/* ATA pass through parameters and function. */
struct grub_disk_ata_pass_through_parms
{
grub_uint8_t taskfile[8];
void * buffer;
int size;
};
extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t,
struct grub_disk_ata_pass_through_parms *);
#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU)
void grub_lvm_init (void);
void grub_mdraid09_init (void);
void grub_mdraid1x_init (void);
void grub_raid_init (void);
void grub_lvm_fini (void);
void grub_mdraid09_fini (void);
void grub_mdraid1x_fini (void);
void grub_raid_fini (void);
#endif
#endif /* ! GRUB_DISK_HEADER */

View File

@ -0,0 +1,123 @@
/* dl.h - types and prototypes for loadable module support */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_DL_H
#define GRUB_DL_H 1
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
//#include <grub/elf.h>
/*
* Macros GRUB_MOD_INIT and GRUB_MOD_FINI are also used by build rules
* to collect module names, so we define them only when they are not
* defined already.
*/
#ifndef GRUB_MOD_INIT
#define GRUB_MOD_INIT(name) \
static void grub_mod_init (grub_dl_t mod __attribute__ ((unused))) __attribute__ ((used)); \
void grub_##name##_init (void); \
void \
grub_##name##_init (void) { grub_mod_init (0); } \
static void \
grub_mod_init (grub_dl_t mod __attribute__ ((unused)))
#endif
#ifndef GRUB_MOD_FINI
#define GRUB_MOD_FINI(name) \
static void grub_mod_fini (void) __attribute__ ((used)); \
void grub_##name##_fini (void); \
void \
grub_##name##_fini (void) { grub_mod_fini (); } \
static void \
grub_mod_fini (void)
#endif
#ifdef APPLE_CC
#define GRUB_MOD_NAME(name) \
static char grub_modname[] __attribute__ ((section ("_modname, _modname"), used)) = #name;
#define GRUB_MOD_DEP(name) \
__asm__ (".section _moddeps, _moddeps\n.asciz \"" #name "\"\n")
#else
#define GRUB_MOD_NAME(name) \
__asm__ (".section .modname\n.asciz \"" #name "\"\n")
#define GRUB_MOD_DEP(name) \
__asm__ (".section .moddeps\n.asciz \"" #name "\"\n")
#endif
struct grub_dl_segment
{
struct grub_dl_segment *next;
void *addr;
grub_size_t size;
unsigned section;
};
typedef struct grub_dl_segment *grub_dl_segment_t;
struct grub_dl;
struct grub_dl_dep
{
struct grub_dl_dep *next;
struct grub_dl *mod;
};
typedef struct grub_dl_dep *grub_dl_dep_t;
struct grub_dl
{
char *name;
int ref_count;
grub_dl_dep_t dep;
grub_dl_segment_t segment;
void *symtab;//Elf_Sym *symtab;
void (*init) (struct grub_dl *mod);
void (*fini) (void);
struct grub_dl *next;
};
typedef struct grub_dl *grub_dl_t;
grub_dl_t EXPORT_FUNC(grub_dl_load_file) (const char *filename);
grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
//void grub_dl_unload_unneeded (void);
//int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
//int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
extern grub_dl_t EXPORT_VAR(grub_dl_head);
#define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head))
grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name);
grub_err_t grub_dl_register_symbol (const char *name, void *addr,
grub_dl_t mod);
grub_err_t grub_arch_dl_check_header (void *ehdr);
grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr);
#if defined (_mips)
#define GRUB_LINKER_HAVE_INIT 1
void grub_arch_dl_init_linker (void);
#endif
#endif /* ! GRUB_DL_H */

View File

@ -0,0 +1,28 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_CONSOLE_UTIL_HEADER
#define GRUB_CONSOLE_UTIL_HEADER 1
/* Initialize the console system. */
void grub_console_init (void);
/* Finish the console system. */
void grub_console_fini (void);
#endif /* ! GRUB_CONSOLE_UTIL_HEADER */

View File

@ -0,0 +1,38 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003, 2007, 2008, 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_UTIL_GETROOT_HEADER
#define GRUB_UTIL_GETROOT_HEADER 1
#include <sys/types.h>
enum grub_dev_abstraction_types {
GRUB_DEV_ABSTRACTION_NONE,
GRUB_DEV_ABSTRACTION_LVM,
GRUB_DEV_ABSTRACTION_RAID,
};
char *grub_find_device (const char *dir, dev_t dev);
char *grub_guess_root_device (const char *dir);
int grub_util_get_dev_abstraction (const char *os_dev);
char *grub_util_get_grub_dev (const char *os_dev);
char *grub_make_system_path_relative_to_its_root (const char *path);
const char *grub_util_check_block_device (const char *blk_dev);
const char *grub_util_check_char_device (const char *blk_dev);
#endif /* ! GRUB_UTIL_GETROOT_HEADER */

View File

@ -0,0 +1,32 @@
/* biosdisk.h - emulate biosdisk */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_BIOSDISK_MACHINE_UTIL_HEADER
#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1
#include <grub/disk.h>
void grub_util_biosdisk_init (const char *dev_map);
void grub_util_biosdisk_fini (void);
char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
const char *grub_util_biosdisk_get_osdev (grub_disk_t disk);
int grub_util_biosdisk_is_present (const char *name);
int grub_util_biosdisk_is_floppy (grub_disk_t disk);
#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */

View File

@ -0,0 +1,81 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_EMU_MISC_H
#define GRUB_EMU_MISC_H 1
#include <config.h>
#include <stdarg.h>
#include <grub/symbol.h>
#include <grub/types.h>
#ifdef __CYGWIN__
# include <sys/fcntl.h>
# include <sys/cygwin.h>
# include <limits.h>
# define DEV_CYGDRIVE_MAJOR 98
#endif
#ifdef __NetBSD__
/* NetBSD uses /boot for its boot block. */
# define DEFAULT_DIRECTORY "/"GRUB_DIR_NAME
#else
# define DEFAULT_DIRECTORY "/"GRUB_BOOT_DIR_NAME"/"GRUB_DIR_NAME
#endif
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
extern int verbosity;
extern const char *program_name;
void grub_emu_init (void);
void grub_init_all (void);
void grub_fini_all (void);
void grub_emu_post_init (void);
void grub_find_zpool_from_dir (const char *dir,
char **poolname, char **poolfs);
char *grub_make_system_path_relative_to_its_root (const char *path)
__attribute__ ((warn_unused_result));
void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result));
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result));
char * EXPORT_FUNC(xstrdup) (const char *str) __attribute__ ((warn_unused_result));
char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((warn_unused_result));
void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...);
void EXPORT_FUNC(grub_util_info) (const char *fmt, ...);
void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((noreturn));
#ifndef HAVE_VASPRINTF
int EXPORT_FUNC(vasprintf) (char **buf, const char *fmt, va_list ap);
#endif
#ifndef HAVE_ASPRINTF
int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...);
#endif
extern char * canonicalize_file_name (const char *path);
#ifdef HAVE_DEVICE_MAPPER
int grub_device_mapper_supported (void);
#endif
#endif /* GRUB_EMU_MISC_H */

View File

@ -0,0 +1,69 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_ENV_HEADER
#define GRUB_ENV_HEADER 1
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
#include <grub/menu.h>
struct grub_env_var;
typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var,
const char *val);
typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var,
const char *val);
struct grub_env_var
{
char *name;
char *value;
grub_env_read_hook_t read_hook;
grub_env_write_hook_t write_hook;
struct grub_env_var *next;
struct grub_env_var **prevp;
int global;
};
grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val);
char *EXPORT_FUNC(grub_env_get) (const char *name);
void EXPORT_FUNC(grub_env_unset) (const char *name);
void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var));
struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name);
grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name,
grub_env_read_hook_t read_hook,
grub_env_write_hook_t write_hook);
grub_err_t grub_env_context_open (void);
grub_err_t grub_env_context_close (void);
grub_err_t grub_env_export (const char *name);
void grub_env_unset_menu (void);
grub_menu_t grub_env_get_menu (void);
void grub_env_set_menu (grub_menu_t nmenu);
grub_err_t
grub_env_extractor_open (int source);
grub_err_t
grub_env_extractor_close (int source);
#endif /* ! GRUB_ENV_HEADER */

View File

@ -0,0 +1,46 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_ENV_PRIVATE_HEADER
#define GRUB_ENV_PRIVATE_HEADER 1
#include <grub/env.h>
/* The size of the hash table. */
#define HASHSZ 13
/* A hashtable for quick lookup of variables. */
struct grub_env_context
{
/* A hash table for variables. */
struct grub_env_var *vars[HASHSZ];
/* One level deeper on the stack. */
struct grub_env_context *prev;
};
/* This is used for sorting only. */
struct grub_env_sorted_var
{
struct grub_env_var *var;
struct grub_env_sorted_var *next;
};
extern struct grub_env_context *EXPORT_VAR(grub_current_context);
#endif /* ! GRUB_ENV_PRIVATE_HEADER */

View File

@ -0,0 +1,74 @@
/* err.h - error numbers and prototypes */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_ERR_HEADER
#define GRUB_ERR_HEADER 1
#include <grub/symbol.h>
typedef enum
{
GRUB_ERR_NONE = 0,
GRUB_ERR_TEST_FAILURE,
GRUB_ERR_BAD_MODULE,
GRUB_ERR_OUT_OF_MEMORY,
GRUB_ERR_BAD_FILE_TYPE,
GRUB_ERR_FILE_NOT_FOUND,
GRUB_ERR_FILE_READ_ERROR,
GRUB_ERR_BAD_FILENAME,
GRUB_ERR_UNKNOWN_FS,
GRUB_ERR_BAD_FS,
GRUB_ERR_BAD_NUMBER,
GRUB_ERR_OUT_OF_RANGE,
GRUB_ERR_UNKNOWN_DEVICE,
GRUB_ERR_BAD_DEVICE,
GRUB_ERR_READ_ERROR,
GRUB_ERR_WRITE_ERROR,
GRUB_ERR_UNKNOWN_COMMAND,
GRUB_ERR_INVALID_COMMAND,
GRUB_ERR_BAD_ARGUMENT,
GRUB_ERR_BAD_PART_TABLE,
GRUB_ERR_UNKNOWN_OS,
GRUB_ERR_BAD_OS,
GRUB_ERR_NO_KERNEL,
GRUB_ERR_BAD_FONT,
GRUB_ERR_NOT_IMPLEMENTED_YET,
GRUB_ERR_SYMLINK_LOOP,
GRUB_ERR_BAD_COMPRESSED_DATA,
GRUB_ERR_MENU,
GRUB_ERR_TIMEOUT,
GRUB_ERR_IO,
GRUB_ERR_ACCESS_DENIED,
GRUB_ERR_EXTRACTOR
}
grub_err_t;
extern grub_err_t EXPORT_VAR(grub_errno);
extern char EXPORT_VAR(grub_errmsg)[];
grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...);
void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_error_push) (void);
int EXPORT_FUNC(grub_error_pop) (void);
void EXPORT_FUNC(grub_print_error) (void);
extern int EXPORT_VAR(grub_err_printed_errors);
int grub_err_printf (const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
#endif /* ! GRUB_ERR_HEADER */

View File

@ -0,0 +1,79 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_EXTCMD_HEADER
#define GRUB_EXTCMD_HEADER 1
#include <grub/lib/arg.h>
#include <grub/command.h>
#include <grub/script_sh.h>
struct grub_extcmd;
struct grub_extcmd_context;
typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd_context *ctxt,
int argc, char **args);
/* The argcmd description. */
struct grub_extcmd
{
grub_command_t cmd;
grub_extcmd_func_t func;
/* The argument parser optionlist. */
const struct grub_arg_option *options;
void *data;
};
typedef struct grub_extcmd *grub_extcmd_t;
/* Command context for each instance of execution. */
struct grub_extcmd_context
{
struct grub_extcmd *extcmd;
struct grub_arg_list *state;
/* Script parameter, if any. */
struct grub_script *script;
};
typedef struct grub_extcmd_context *grub_extcmd_context_t;
grub_extcmd_t EXPORT_FUNC(grub_register_extcmd) (const char *name,
grub_extcmd_func_t func,
grub_command_flags_t flags,
const char *summary,
const char *description,
const struct grub_arg_option *parser);
grub_extcmd_t EXPORT_FUNC(grub_register_extcmd_prio) (const char *name,
grub_extcmd_func_t func,
grub_command_flags_t flags,
const char *summary,
const char *description,
const struct grub_arg_option *parser,
int prio);
void EXPORT_FUNC(grub_unregister_extcmd) (grub_extcmd_t cmd);
grub_err_t EXPORT_FUNC(grub_extcmd_dispatcher) (struct grub_command *cmd,
int argc, char **args,
struct grub_script *script);
#endif /* ! GRUB_EXTCMD_HEADER */

View File

@ -0,0 +1,129 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_FILE_HEADER
#define GRUB_FILE_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
#include <grub/device.h>
#include <grub/fs.h>
/* File description. */
struct grub_file
{
/* The underlying device. */
grub_device_t device;
/* The underlying filesystem. */
grub_fs_t fs;
/* The current offset. */
grub_off_t offset;
/* The file size. */
grub_off_t size;
/* If file is not easly seekable. Should be set by underlying layer. */
int not_easly_seekable;
/* Filesystem-specific data. */
void *data;
/* This is called when a sector is read. Used only for a disk device. */
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length);
};
typedef struct grub_file *grub_file_t;
/* Filters with lower ID are executed first. */
typedef enum grub_file_filter_id
{
GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_XZIO,
GRUB_FILE_FILTER_MAX,
GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_XZIO,
} grub_file_filter_id_t;
typedef grub_file_t (*grub_file_filter_t) (grub_file_t in);
extern grub_file_filter_t EXPORT_VAR(grub_file_filters_all)[GRUB_FILE_FILTER_MAX];
extern grub_file_filter_t EXPORT_VAR(grub_file_filters_enabled)[GRUB_FILE_FILTER_MAX];
static inline void
grub_file_filter_register (grub_file_filter_id_t id, grub_file_filter_t filter)
{
grub_file_filters_all[id] = filter;
grub_file_filters_enabled[id] = filter;
};
static inline void
grub_file_filter_unregister (grub_file_filter_id_t id)
{
grub_file_filters_all[id] = 0;
grub_file_filters_enabled[id] = 0;
};
static inline void
grub_file_filter_disable (grub_file_filter_id_t id)
{
grub_file_filters_enabled[id] = 0;
};
static inline void
grub_file_filter_disable_compression (void)
{
grub_file_filter_id_t id;
for (id = GRUB_FILE_FILTER_COMPRESSION_FIRST;
id <= GRUB_FILE_FILTER_COMPRESSION_LAST; id++)
grub_file_filters_enabled[id] = 0;
};
/* Get a device name from NAME. */
char *EXPORT_FUNC(grub_file_get_device_name) (const char *name);
grub_file_t EXPORT_FUNC(grub_file_open) (const char *name);
grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
grub_size_t len);
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
/* Return value of grub_file_size() in case file size is unknown. */
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL
static inline grub_off_t
grub_file_size (const grub_file_t file)
{
return file->size;
}
static inline grub_off_t
grub_file_tell (const grub_file_t file)
{
return file->offset;
}
static inline int
grub_file_seekable (const grub_file_t file)
{
return !file->not_easly_seekable;
}
#endif /* ! GRUB_FILE_HEADER */

View File

@ -0,0 +1,112 @@
/* fs.h - filesystem manager */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_FS_HEADER
#define GRUB_FS_HEADER 1
#include <grub/device.h>
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/list.h>
/* Forward declaration is required, because of mutual reference. */
struct grub_file;
struct grub_dirhook_info
{
int dir:1;
int mtimeset:1;
int case_insensitive:1;
grub_int32_t mtime;
};
/* Filesystem descriptor. */
struct grub_fs
{
/* The next filesystem. */
struct grub_fs *next;
/* My name. */
const char *name;
/* Call HOOK with each file under DIR. */
grub_err_t (*dir) (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info));
/* Open a file named NAME and initialize FILE. */
grub_err_t (*open) (struct grub_file *file, const char *name);
/* Read LEN bytes data from FILE into BUF. */
grub_ssize_t (*read) (struct grub_file *file, char *buf, grub_size_t len);
/* Close the file FILE. */
grub_err_t (*close) (struct grub_file *file);
/* Return the label of the device DEVICE in LABEL. The label is
returned in a grub_malloc'ed buffer and should be freed by the
caller. */
grub_err_t (*label) (grub_device_t device, char **label);
/* Return the uuid of the device DEVICE in UUID. The uuid is
returned in a grub_malloc'ed buffer and should be freed by the
caller. */
grub_err_t (*uuid) (grub_device_t device, char **uuid);
/* Get writing time of filesystem. */
grub_err_t (*mtime) (grub_device_t device, grub_int32_t *timebuf);
#ifdef GRUB_UTIL
/* Whether this filesystem reserves first sector for DOS-style boot. */
int reserved_first_sector;
#endif
};
typedef struct grub_fs *grub_fs_t;
/* This is special, because block lists are not files in usual sense. */
extern struct grub_fs grub_fs_blocklist;
/* This hook is used to automatically load filesystem modules.
If this hook loads a module, return non-zero. Otherwise return zero.
The newly loaded filesystem is assumed to be inserted into the head of
the linked list GRUB_FS_LIST through the function grub_fs_register. */
typedef int (*grub_fs_autoload_hook_t) (void);
extern grub_fs_autoload_hook_t EXPORT_VAR(grub_fs_autoload_hook);
extern grub_fs_t EXPORT_VAR (grub_fs_list);
#ifndef GRUB_LST_GENERATOR
static inline void
grub_fs_register (grub_fs_t fs)
{
grub_list_push (GRUB_AS_LIST_P (&grub_fs_list), GRUB_AS_LIST (fs));
}
#endif
static inline void
grub_fs_unregister (grub_fs_t fs)
{
grub_list_remove (GRUB_AS_LIST_P (&grub_fs_list), GRUB_AS_LIST (fs));
}
#define FOR_FILESYSTEMS(var) FOR_LIST_ELEMENTS((var), (grub_fs_list))
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
#endif /* ! GRUB_FS_HEADER */

View File

@ -0,0 +1,82 @@
/* fshelp.h -- Filesystem helper functions */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_FSHELP_HEADER
#define GRUB_FSHELP_HEADER 1
#include <grub/types.h>
#include <grub/symbol.h>
#include <grub/err.h>
typedef struct grub_fshelp_node *grub_fshelp_node_t;
#define GRUB_FSHELP_CASE_INSENSITIVE 0x100
#define GRUB_FSHELP_TYPE_MASK 0xff
#define GRUB_FSHELP_FLAGS_MASK 0x100
enum grub_fshelp_filetype
{
GRUB_FSHELP_UNKNOWN,
GRUB_FSHELP_REG,
GRUB_FSHELP_DIR,
GRUB_FSHELP_SYMLINK
};
/* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
iterate over all directory entries in the current node.
READ_SYMLINK is used to read the symlink if a node is a symlink.
EXPECTTYPE is the type node that is expected by the called, an
error is generated if the node is not of the expected type. Make
sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required
because GCC has a nasty bug when using regparm=3. */
grub_err_t
EXPORT_FUNC(grub_fshelp_find_file) (const char *path,
grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
int (*iterate_dir) (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)),
char *(*read_symlink) (grub_fshelp_node_t node),
enum grub_fshelp_filetype expect);
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
beginning with the block POS. READ_HOOK should be set before
reading a block from the file. GET_BLOCK is used to translate file
blocks to disk blocks. The file is FILESIZE bytes big and the
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
EXPORT_FUNC(grub_fshelp_read_file) (grub_disk_t disk, grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset,
unsigned length),
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize);
unsigned int
EXPORT_FUNC(grub_fshelp_log2blksize) (unsigned int blksize,
unsigned int *pow);
#endif /* ! GRUB_FSHELP_HEADER */

View File

@ -0,0 +1,71 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2005,2006,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_GPT_PARTITION_HEADER
#define GRUB_GPT_PARTITION_HEADER 1
#include <grub/types.h>
struct grub_gpt_part_type
{
grub_uint32_t data1;
grub_uint16_t data2;
grub_uint16_t data3;
grub_uint8_t data4[8];
} __attribute__ ((aligned(8)));
typedef struct grub_gpt_part_type grub_gpt_part_type_t;
#define GRUB_GPT_PARTITION_TYPE_EMPTY \
{ 0x0, 0x0, 0x0, \
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } \
}
#define GRUB_GPT_PARTITION_TYPE_BIOS_BOOT \
{ grub_cpu_to_le32_compile_time (0x21686148), grub_cpu_to_le16_compile_time (0x6449), grub_cpu_to_le16_compile_time (0x6e6f), \
{ 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } \
}
struct grub_gpt_header
{
grub_uint8_t magic[8];
grub_uint32_t version;
grub_uint32_t headersize;
grub_uint32_t crc32;
grub_uint32_t unused1;
grub_uint64_t primary;
grub_uint64_t backup;
grub_uint64_t start;
grub_uint64_t end;
grub_uint8_t guid[16];
grub_uint64_t partitions;
grub_uint32_t maxpart;
grub_uint32_t partentry_size;
grub_uint32_t partentry_crc32;
} __attribute__ ((packed));
struct grub_gpt_partentry
{
grub_gpt_part_type_t type;
grub_uint8_t guid[16];
grub_uint64_t start;
grub_uint64_t end;
grub_uint64_t attrib;
char name[72];
} __attribute__ ((packed));
#endif /* ! GRUB_GPT_PARTITION_HEADER */

View File

@ -0,0 +1,61 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_HFS_HEADER
#define GRUB_HFS_HEADER 1
#include <grub/types.h>
#define GRUB_HFS_MAGIC 0x4244
/* A single extent. A file consists of one or more extents. */
struct grub_hfs_extent
{
/* The first physical block. */
grub_uint16_t first_block;
grub_uint16_t count;
};
/* HFS stores extents in groups of 3. */
typedef struct grub_hfs_extent grub_hfs_datarecord_t[3];
/* The HFS superblock (The official name is `Master Directory
Block'). */
struct grub_hfs_sblock
{
grub_uint16_t magic;
grub_uint8_t unused[18];
grub_uint32_t blksz;
grub_uint8_t unused2[4];
grub_uint16_t first_block;
grub_uint8_t unused4[6];
/* A pascal style string that holds the volumename. */
grub_uint8_t volname[28];
grub_uint8_t unused5[52];
grub_uint64_t num_serial;
grub_uint16_t embed_sig;
struct grub_hfs_extent embed_extent;
grub_uint8_t unused6[4];
grub_hfs_datarecord_t extent_recs;
grub_uint32_t catalog_size;
grub_hfs_datarecord_t catalog_recs;
} __attribute__ ((packed));
#endif /* ! GRUB_HFS_HEADER */

View File

@ -0,0 +1,68 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_I18N_H
#define GRUB_I18N_H 1
#include <config.h>
#include <grub/symbol.h>
/* NLS can be disabled through the configure --disable-nls option. */
#if (defined(ENABLE_NLS) && ENABLE_NLS) || !defined (GRUB_UTIL)
extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
# ifdef GRUB_UTIL
# include <locale.h>
# include <libintl.h>
# endif /* GRUB_UTIL */
#else /* ! (defined(ENABLE_NLS) && ENABLE_NLS) */
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
static inline const char * __attribute__ ((always_inline))
gettext (const char *str)
{
return str;
}
#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
#ifdef GRUB_UTIL
static inline const char * __attribute__ ((always_inline))
_ (const char *str)
{
return gettext(str);
}
#else
static inline const char * __attribute__ ((always_inline))
_ (const char *str)
{
return grub_gettext(str);
}
#endif /* GRUB_UTIL */
#define N_(str) str
#endif /* GRUB_I18N_H */

View File

@ -0,0 +1,117 @@
/* list.h - header for grub list */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_LIST_HEADER
#define GRUB_LIST_HEADER 1
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/misc.h>
struct grub_list
{
struct grub_list *next;
};
typedef struct grub_list *grub_list_t;
void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item);
void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, grub_list_t item);
#define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next)
static inline void *
grub_bad_type_cast_real (int line, const char *file)
ATTRIBUTE_ERROR ("bad type cast between incompatible grub types");
static inline void *
grub_bad_type_cast_real (int line, const char *file)
{
grub_fatal ("error:%s:%u: bad type cast between incompatible grub types",
file, line);
return 0;
}
#define grub_bad_type_cast() grub_bad_type_cast_real(__LINE__, GRUB_FILE)
#define GRUB_FIELD_MATCH(ptr, type, field) \
((char *) &(ptr)->field == (char *) &((type) (ptr))->field)
#define GRUB_AS_LIST(ptr) \
(GRUB_FIELD_MATCH (ptr, grub_list_t, next) ? \
(grub_list_t) ptr : grub_bad_type_cast ())
#define GRUB_AS_LIST_P(pptr) \
(GRUB_FIELD_MATCH (*pptr, grub_list_t, next) ? \
(grub_list_t *) (void *) pptr : grub_bad_type_cast ())
struct grub_named_list
{
struct grub_named_list *next;
char *name;
};
typedef struct grub_named_list *grub_named_list_t;
void * EXPORT_FUNC(grub_named_list_find) (grub_named_list_t head,
const char *name);
#define GRUB_AS_NAMED_LIST(ptr) \
((GRUB_FIELD_MATCH (ptr, grub_named_list_t, next) && \
GRUB_FIELD_MATCH (ptr, grub_named_list_t, name))? \
(grub_named_list_t) ptr : grub_bad_type_cast ())
#define GRUB_AS_NAMED_LIST_P(pptr) \
((GRUB_FIELD_MATCH (*pptr, grub_named_list_t, next) && \
GRUB_FIELD_MATCH (*pptr, grub_named_list_t, name))? \
(grub_named_list_t *) (void *) pptr : grub_bad_type_cast ())
#define GRUB_PRIO_LIST_PRIO_MASK 0xff
#define GRUB_PRIO_LIST_FLAG_ACTIVE 0x100
struct grub_prio_list
{
struct grub_prio_list *next;
char *name;
int prio;
};
typedef struct grub_prio_list *grub_prio_list_t;
void EXPORT_FUNC(grub_prio_list_insert) (grub_prio_list_t *head,
grub_prio_list_t item);
static inline void
grub_prio_list_remove (grub_prio_list_t *head, grub_prio_list_t item)
{
if ((item->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && (item->next))
item->next->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE;
grub_list_remove (GRUB_AS_LIST_P (head), GRUB_AS_LIST (item));
}
#define GRUB_AS_PRIO_LIST(ptr) \
((GRUB_FIELD_MATCH (ptr, grub_prio_list_t, next) && \
GRUB_FIELD_MATCH (ptr, grub_prio_list_t, name) && \
GRUB_FIELD_MATCH (ptr, grub_prio_list_t, prio))? \
(grub_prio_list_t) ptr : grub_bad_type_cast ())
#define GRUB_AS_PRIO_LIST_P(pptr) \
((GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, next) && \
GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, name) && \
GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prio))? \
(grub_prio_list_t *) (void *) pptr : grub_bad_type_cast ())
#endif /* ! GRUB_LIST_HEADER */

View File

@ -0,0 +1,66 @@
/* loader.h - OS loaders */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,2006,2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_LOADER_HEADER
#define GRUB_LOADER_HEADER 1
#include <grub/file.h>
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
/* Check if a loader is loaded. */
int EXPORT_FUNC (grub_loader_is_loaded) (void);
/* Set loader functions. NORETURN must be set to true, if BOOT won't return
to the original state. */
void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
grub_err_t (*unload) (void),
int noreturn);
/* Unset current loader, if any. */
void EXPORT_FUNC (grub_loader_unset) (void);
/* Call the boot hook in current loader. This may or may not return,
depending on the setting by grub_loader_set. */
grub_err_t grub_loader_boot (void);
/* The space between numbers is intentional for the simplicity of adding new
values even if external modules use them. */
typedef enum {
/* A preboot hook which can use everything and turns nothing off. */
GRUB_LOADER_PREBOOT_HOOK_PRIO_NORMAL = 400,
/* A preboot hook which can't use disks and may stop disks. */
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK = 300,
/* A preboot hook which can't use disks or console and may stop console. */
GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE = 200,
/* A preboot hook which can't use disks or console, can't modify memory map
and may stop memory services or finalize memory map. */
GRUB_LOADER_PREBOOT_HOOK_PRIO_MEMORY = 100,
} grub_loader_preboot_hook_prio_t;
/* Register a preboot hook. */
void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret),
grub_err_t (*preboot_rest_func) (void),
grub_loader_preboot_hook_prio_t prio);
/* Unregister given preboot hook. */
void grub_loader_unregister_preboot_hook (void *hnd);
#endif /* ! GRUB_LOADER_HEADER */

View File

@ -0,0 +1,129 @@
/* lvm.h - On disk structures for LVM. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_LVM_H
#define GRUB_LVM_H 1
#include <grub/types.h>
/* Length of ID string, excluding terminating zero. */
#define GRUB_LVM_ID_STRLEN 38
struct grub_lvm_vg {
char id[GRUB_LVM_ID_STRLEN+1];
char *name;
int extent_size;
struct grub_lvm_pv *pvs;
struct grub_lvm_lv *lvs;
struct grub_lvm_vg *next;
};
struct grub_lvm_pv {
char id[GRUB_LVM_ID_STRLEN+1];
char *name;
grub_disk_t disk;
int start; /* Sector number where the data area starts. */
struct grub_lvm_pv *next;
};
struct grub_lvm_lv {
char *name;
unsigned int number;
unsigned int segment_count;
grub_uint64_t size;
struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */
struct grub_lvm_vg *vg;
struct grub_lvm_lv *next;
};
struct grub_lvm_segment {
unsigned int start_extent;
unsigned int extent_count;
unsigned int stripe_count;
unsigned int stripe_size;
struct grub_lvm_stripe *stripes; /* Pointer to stripe_count stripes. */
};
struct grub_lvm_stripe {
int start;
struct grub_lvm_pv *pv;
};
#define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE
#define GRUB_LVM_LABEL_SCAN_SECTORS 4L
#define GRUB_LVM_LABEL_ID "LABELONE"
#define GRUB_LVM_LVM2_LABEL "LVM2 001"
#define GRUB_LVM_ID_LEN 32
/* On disk - 32 bytes */
struct grub_lvm_label_header {
grub_int8_t id[8]; /* LABELONE */
grub_uint64_t sector_xl; /* Sector number of this label */
grub_uint32_t crc_xl; /* From next field to end of sector */
grub_uint32_t offset_xl; /* Offset from start of struct to contents */
grub_int8_t type[8]; /* LVM2 001 */
} __attribute__ ((packed));
/* On disk */
struct grub_lvm_disk_locn {
grub_uint64_t offset; /* Offset in bytes to start sector */
grub_uint64_t size; /* Bytes */
} __attribute__ ((packed));
/* Fields with the suffix _xl should be xlate'd wherever they appear */
/* On disk */
struct grub_lvm_pv_header {
grub_int8_t pv_uuid[GRUB_LVM_ID_LEN];
/* This size can be overridden if PV belongs to a VG */
grub_uint64_t device_size_xl; /* Bytes */
/* NULL-terminated list of data areas followed by */
/* NULL-terminated list of metadata area headers */
struct grub_lvm_disk_locn disk_areas_xl[0]; /* Two lists */
} __attribute__ ((packed));
#define GRUB_LVM_FMTT_MAGIC "\040\114\126\115\062\040\170\133\065\101\045\162\060\116\052\076"
#define GRUB_LVM_FMTT_VERSION 1
#define GRUB_LVM_MDA_HEADER_SIZE 512
/* On disk */
struct grub_lvm_raw_locn {
grub_uint64_t offset; /* Offset in bytes to start sector */
grub_uint64_t size; /* Bytes */
grub_uint32_t checksum;
grub_uint32_t filler;
} __attribute__ ((packed));
/* On disk */
/* Structure size limited to one sector */
struct grub_lvm_mda_header {
grub_uint32_t checksum_xl; /* Checksum of rest of mda_header */
grub_int8_t magic[16]; /* To aid scans for metadata */
grub_uint32_t version;
grub_uint64_t start; /* Absolute start byte of mda_header */
grub_uint64_t size; /* Size of metadata area */
struct grub_lvm_raw_locn raw_locns[0]; /* NULL-terminated list */
} __attribute__ ((packed));
#endif /* ! GRUB_LVM_H */

View File

@ -0,0 +1,73 @@
/* memory.h - describe the memory map */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MEMORY_HEADER
#define GRUB_MEMORY_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
typedef enum grub_memory_type
{
GRUB_MEMORY_AVAILABLE = 1,
GRUB_MEMORY_RESERVED = 2,
GRUB_MEMORY_ACPI = 3,
GRUB_MEMORY_NVS = 4,
GRUB_MEMORY_BADRAM = 5,
GRUB_MEMORY_CODE = 20,
/* This one is special: it's used internally but is never reported
by firmware. */
GRUB_MEMORY_HOLE = 21
} grub_memory_type_t;
typedef int NESTED_FUNC_ATTR (*grub_memory_hook_t) (grub_uint64_t,
grub_uint64_t,
grub_memory_type_t);
grub_err_t grub_mmap_iterate (grub_memory_hook_t hook);
#if !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_EFI)
grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) (grub_memory_hook_t hook);
#else
grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook);
#endif
int grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type);
grub_err_t grub_mmap_unregister (int handle);
void *grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size,
int *handle, int type, int flags);
void grub_mmap_free_and_unregister (int handle);
#ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE
struct grub_mmap_region
{
struct grub_mmap_region *next;
grub_uint64_t start;
grub_uint64_t end;
grub_memory_type_t type;
int handle;
};
extern struct grub_mmap_region *grub_mmap_overlays;
#endif
#endif /* ! GRUB_MEMORY_HEADER */

View File

@ -0,0 +1,108 @@
/* menu.h - Menu model function prototypes and data structures. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MENU_HEADER
#define GRUB_MENU_HEADER 1
struct grub_menu_entry_class
{
char *name;
struct grub_menu_entry_class *next;
};
/* The menu entry. */
struct grub_menu_entry
{
/* The title name. */
const char *title;
/* If set means not everybody is allowed to boot this entry. */
int restricted;
/* Allowed users. */
const char *users;
/* The classes associated with the menu entry:
used to choose an icon or other style attributes.
This is a dummy head node for the linked list, so for an entry E,
E.classes->next is the first class if it is not NULL. */
struct grub_menu_entry_class *classes;
/* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode;
/* Parameters to be passed to menu definition. */
int argc;
char **args;
int hotkey;
int submenu;
/* The next element. */
struct grub_menu_entry *next;
};
typedef struct grub_menu_entry *grub_menu_entry_t;
/* The menu. */
struct grub_menu
{
/* The size of a menu. */
int size;
/* The list of menu entries. */
grub_menu_entry_t entry_list;
};
typedef struct grub_menu *grub_menu_t;
/* Callback structure menu viewers can use to provide user feedback when
default entries are executed, possibly including fallback entries. */
typedef struct grub_menu_execute_callback
{
/* Called immediately before ENTRY is booted. */
void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
/* Called when executing one entry has failed, and another entry, ENTRY, will
be executed as a fallback. The implementation of this function should
delay for a period of at least 2 seconds before returning in order to
allow the user time to read the information before it can be lost by
executing ENTRY. */
void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
/* Called when an entry has failed to execute and there is no remaining
fallback entry to attempt. */
void (*notify_failure) (void *userdata);
}
*grub_menu_execute_callback_t;
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
int grub_menu_get_timeout (void);
void grub_menu_set_timeout (int timeout);
void grub_menu_execute_entry (grub_menu_entry_t entry);
void grub_menu_execute_with_fallback (grub_menu_t menu,
grub_menu_entry_t entry,
grub_menu_execute_callback_t callback,
void *callback_data);
void grub_menu_entry_run (grub_menu_entry_t entry);
int grub_menu_get_default_entry_index (grub_menu_t menu);
void grub_menu_init (void);
void grub_menu_fini (void);
#endif /* GRUB_MENU_HEADER */

View File

@ -0,0 +1,48 @@
/* menu_viewer.h - Interface to menu viewer implementations. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MENU_VIEWER_HEADER
#define GRUB_MENU_VIEWER_HEADER 1
#include <grub/err.h>
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/menu.h>
#include <grub/term.h>
struct grub_menu_viewer
{
struct grub_menu_viewer *next;
void *data;
void (*set_chosen_entry) (int entry, void *data);
void (*print_timeout) (int timeout, void *data);
void (*clear_timeout) (void *data);
void (*fini) (void *fini);
};
void grub_menu_register_viewer (struct grub_menu_viewer *viewer);
grub_err_t
grub_menu_try_text (struct grub_term_output *term,
int entry, grub_menu_t menu, int nested);
extern grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested);
#endif /* GRUB_MENU_VIEWER_HEADER */

View File

@ -0,0 +1,356 @@
/* misc.h - prototypes for misc functions */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MISC_HEADER
#define GRUB_MISC_HEADER 1
#include <stdarg.h>
#include <grub/types.h>
#include <grub/symbol.h>
#include <grub/err.h>
/* GCC version checking borrowed from glibc. */
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(maj,min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define GNUC_PREREQ(maj,min) 0
#endif
/* Does this compiler support compile-time error attributes? */
#if GNUC_PREREQ(4,3)
# define ATTRIBUTE_ERROR(msg) \
__attribute__ ((__error__ (msg)))
#else
# define ATTRIBUTE_ERROR(msg)
#endif
#define ALIGN_UP(addr, align) \
((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1))
#define ALIGN_DOWN(addr, align) \
((addr) & ~((typeof (addr)) align - 1))
#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; }
#define grub_dprintf(condition, fmt, args...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, fmt, ## args)
/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */
#define grub_memcpy(d,s,n) grub_memmove ((d), (s), (n))
void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n);
char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src);
char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c);
char *EXPORT_FUNC(grub_stpcpy) (char *dest, const char *src);
static inline char *
grub_strcat (char *dest, const char *src)
{
char *p = dest;
while (*p)
p++;
while ((*p = *src) != '\0')
{
p++;
src++;
}
return dest;
}
static inline char *
grub_strncat (char *dest, const char *src, int c)
{
char *p = dest;
while (*p)
p++;
while ((*p = *src) != '\0' && c--)
{
p++;
src++;
}
*p = '\0';
return dest;
}
/* Prototypes for aliases. */
#ifndef GRUB_UTIL
int EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n);
void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n);
void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n);
void *EXPORT_FUNC(memset) (void *s, int c, grub_size_t n);
#endif
int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n);
int EXPORT_FUNC(grub_strcmp) (const char *s1, const char *s2);
int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n);
char *EXPORT_FUNC(grub_strchr) (const char *s, int c);
char *EXPORT_FUNC(grub_strrchr) (const char *s, int c);
int EXPORT_FUNC(grub_strword) (const char *s, const char *w);
char *EXPORT_FUNC(grub_strstr) (const char *haystack, const char *needle);
int EXPORT_FUNC(grub_isspace) (int c);
int EXPORT_FUNC(grub_isprint) (int c);
static inline int
grub_iscntrl (int c)
{
return (c >= 0x00 && c <= 0x1F) || c == 0x7F;
}
static inline int
grub_isalpha (int c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
static inline int
grub_isgraph (int c)
{
return (c >= '!' && c <= '~');
}
static inline int
grub_isdigit (int c)
{
return (c >= '0' && c <= '9');
}
static inline int
grub_isalnum (int c)
{
return grub_isalpha (c) || grub_isdigit (c);
}
static inline int
grub_tolower (int c)
{
if (c >= 'A' && c <= 'Z')
return c - 'A' + 'a';
return c;
}
static inline int
grub_toupper (int c)
{
if (c >= 'a' && c <= 'z')
return c - 'a' + 'A';
return c;
}
static inline int
grub_strcasecmp (const char *s1, const char *s2)
{
while (*s1 && *s2)
{
if (grub_tolower (*s1) != grub_tolower (*s2))
break;
s1++;
s2++;
}
return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
}
static inline int
grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
{
if (n == 0)
return 0;
while (*s1 && *s2 && --n)
{
if (grub_tolower (*s1) != grub_tolower (*s2))
break;
s1++;
s2++;
}
return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
}
/* Replace all `ch' characters of `input' with `with' and copy the
result into `output'; return EOS address of `output'. */
static inline char *
grub_strchrsub (char *output, const char *input, char ch, const char *with)
{
grub_size_t grub_strlen (const char *s);
while (*input)
{
if (*input == ch)
{
grub_strcpy (output, with);
output += grub_strlen (with);
input++;
continue;
}
*output++ = *input++;
}
*output = '\0';
return output;
}
unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base);
unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base);
static inline long
grub_strtol (const char *str, char **end, int base)
{
int negative = 0;
unsigned long magnitude;
while (*str && grub_isspace (*str))
str++;
if (*str == '-')
{
negative = 1;
str++;
}
magnitude = grub_strtoull (str, end, base);
if (negative)
{
if (magnitude > (unsigned long) GRUB_LONG_MAX + 1)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "negative overflow");
return GRUB_LONG_MIN;
}
return -((long) magnitude);
}
else
{
if (magnitude > GRUB_LONG_MAX)
{
grub_error (GRUB_ERR_OUT_OF_RANGE, "positive overflow");
return GRUB_LONG_MAX;
}
return (long) magnitude;
}
}
char *EXPORT_FUNC(grub_strdup) (const char *s) __attribute__ ((warn_unused_result));
char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n) __attribute__ ((warn_unused_result));
void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n);
grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) __attribute__ ((warn_unused_result));
int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
extern void (*EXPORT_VAR (grub_xputs)) (const char *str);
static inline int
grub_puts (const char *s)
{
const char nl[2] = "\n";
grub_xputs (s);
grub_xputs (nl);
return 1; /* Cannot fail. */
}
int EXPORT_FUNC(grub_puts_) (const char *s);
void EXPORT_FUNC(grub_real_dprintf) (const char *file,
const int line,
const char *condition,
const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args);
int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...)
__attribute__ ((format (printf, 3, 4)));
int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt,
va_list args);
char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))) __attribute__ ((warn_unused_result));
char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__ ((warn_unused_result));
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint32_t d, grub_uint32_t *r);
#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL)
void EXPORT_FUNC(__enable_execute_stack) (void *addr);
#endif
#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL)
void EXPORT_FUNC (__register_frame_info) (void);
void EXPORT_FUNC (__deregister_frame_info) (void);
#endif
/* Inline functions. */
static inline unsigned int
grub_abs (int x)
{
if (x < 0)
return (unsigned int) (-x);
else
return (unsigned int) x;
}
static inline long
grub_min (long x, long y)
{
if (x < y)
return x;
else
return y;
}
static inline long
grub_max (long x, long y)
{
if (x > y)
return x;
else
return y;
}
/* Rounded-up division */
static inline unsigned int
grub_div_roundup (unsigned int x, unsigned int y)
{
return (x + y - 1) / y;
}
/* Reboot the machine. */
void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn));
#ifdef GRUB_MACHINE_PCBIOS
/* Halt the system, using APM if possible. If NO_APM is true, don't
* use APM even if it is available. */
void grub_halt (int no_apm) __attribute__ ((noreturn));
#else
void grub_halt (void) __attribute__ ((noreturn));
#endif
#ifdef GRUB_MACHINE_EMU
/* Flag to control module autoloading in normal mode. */
extern int EXPORT_VAR(grub_no_autoload);
#else
#define grub_no_autoload 0
#endif
#endif /* ! GRUB_MISC_HEADER */

View File

@ -0,0 +1,77 @@
/* mm.h - prototypes and declarations for memory manager */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MM_H
#define GRUB_MM_H 1
#include <grub/types.h>
#include <grub/symbol.h>
#include <config.h>
#ifndef NULL
# define NULL ((void *) 0)
#endif
#if 0
void grub_mm_init_region (void *addr, grub_size_t size);
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
void EXPORT_FUNC(grub_free) (void *ptr);
void *EXPORT_FUNC(grub_realloc) (void *ptr, grub_size_t size);
void *EXPORT_FUNC(grub_memalign) (grub_size_t align, grub_size_t size);
#endif
void grub_mm_check_real (char *file, int line);
#define GRUB_MM_CHECK grub_mm_check_real (__FILE__, __LINE__);
/* For debugging. */
#if defined(MM_DEBUG) && !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
/* Set this variable to 1 when you want to trace all memory function calls. */
extern int EXPORT_VAR(grub_mm_debug);
void grub_mm_dump_free (void);
void grub_mm_dump (unsigned lineno);
#define grub_malloc(size) \
grub_debug_malloc (GRUB_FILE, __LINE__, size)
#define grub_zalloc(size) \
grub_debug_zalloc (GRUB_FILE, __LINE__, size)
#define grub_realloc(ptr,size) \
grub_debug_realloc (GRUB_FILE, __LINE__, ptr, size)
#define grub_memalign(align,size) \
grub_debug_memalign (GRUB_FILE, __LINE__, align, size)
#define grub_free(ptr) \
grub_debug_free (GRUB_FILE, __LINE__, ptr)
void *EXPORT_FUNC(grub_debug_malloc) (const char *file, int line,
grub_size_t size);
void *EXPORT_FUNC(grub_debug_zalloc) (const char *file, int line,
grub_size_t size);
void EXPORT_FUNC(grub_debug_free) (const char *file, int line, void *ptr);
void *EXPORT_FUNC(grub_debug_realloc) (const char *file, int line, void *ptr,
grub_size_t size);
void *EXPORT_FUNC(grub_debug_memalign) (const char *file, int line,
grub_size_t align, grub_size_t size);
#endif /* MM_DEBUG && ! GRUB_UTIL */
#endif /* ! GRUB_MM_H */

View File

@ -0,0 +1,64 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MM_PRIVATE_H
#define GRUB_MM_PRIVATE_H 1
#include <grub/mm.h>
/* Magic words. */
#define GRUB_MM_FREE_MAGIC 0x2d3c2808
#define GRUB_MM_ALLOC_MAGIC 0x6db08fa4
typedef struct grub_mm_header
{
struct grub_mm_header *next;
grub_size_t size;
grub_size_t magic;
#if GRUB_CPU_SIZEOF_VOID_P == 4
char padding[4];
#elif GRUB_CPU_SIZEOF_VOID_P == 8
char padding[8];
#else
# error "unknown word size"
#endif
}
*grub_mm_header_t;
#if GRUB_CPU_SIZEOF_VOID_P == 4
# define GRUB_MM_ALIGN_LOG2 4
#elif GRUB_CPU_SIZEOF_VOID_P == 8
# define GRUB_MM_ALIGN_LOG2 5
#endif
#define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2)
typedef struct grub_mm_region
{
struct grub_mm_header *first;
struct grub_mm_region *next;
grub_size_t pre_size;
grub_size_t size;
}
*grub_mm_region_t;
#ifndef GRUB_MACHINE_EMU
extern grub_mm_region_t EXPORT_VAR (grub_mm_base);
#endif
#endif

View File

@ -0,0 +1,124 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2004,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PC_PARTITION_HEADER
#define GRUB_PC_PARTITION_HEADER 1
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/disk.h>
#include <grub/partition.h>
/* The signature. */
#define GRUB_PC_PARTITION_SIGNATURE 0xaa55
/* This is not a flag actually, but used as if it were a flag. */
#define GRUB_PC_PARTITION_TYPE_HIDDEN_FLAG 0x10
/* DOS partition types. */
#define GRUB_PC_PARTITION_TYPE_NONE 0
#define GRUB_PC_PARTITION_TYPE_FAT12 1
#define GRUB_PC_PARTITION_TYPE_FAT16_LT32M 4
#define GRUB_PC_PARTITION_TYPE_EXTENDED 5
#define GRUB_PC_PARTITION_TYPE_FAT16_GT32M 6
#define GRUB_PC_PARTITION_TYPE_NTFS 7
#define GRUB_PC_PARTITION_TYPE_FAT32 0xb
#define GRUB_PC_PARTITION_TYPE_FAT32_LBA 0xc
#define GRUB_PC_PARTITION_TYPE_FAT16_LBA 0xe
#define GRUB_PC_PARTITION_TYPE_WIN95_EXTENDED 0xf
#define GRUB_PC_PARTITION_TYPE_EZD 0x55
#define GRUB_PC_PARTITION_TYPE_MINIX 0x80
#define GRUB_PC_PARTITION_TYPE_LINUX_MINIX 0x81
#define GRUB_PC_PARTITION_TYPE_EXT2FS 0x83
#define GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED 0x85
#define GRUB_PC_PARTITION_TYPE_VSTAFS 0x9e
#define GRUB_PC_PARTITION_TYPE_FREEBSD 0xa5
#define GRUB_PC_PARTITION_TYPE_OPENBSD 0xa6
#define GRUB_PC_PARTITION_TYPE_NETBSD 0xa9
#define GRUB_PC_PARTITION_TYPE_HFS 0xaf
#define GRUB_PC_PARTITION_TYPE_GPT_DISK 0xee
#define GRUB_PC_PARTITION_TYPE_LINUX_RAID 0xfd
/* The partition entry. */
struct grub_msdos_partition_entry
{
/* If active, 0x80, otherwise, 0x00. */
grub_uint8_t flag;
/* The head of the start. */
grub_uint8_t start_head;
/* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C
is the cylinder of the start. Note that S is counted from one. */
grub_uint8_t start_sector;
/* (C & 0xFF) where C is the cylinder of the start. */
grub_uint8_t start_cylinder;
/* The partition type. */
grub_uint8_t type;
/* The end versions of start_head, start_sector and start_cylinder,
respectively. */
grub_uint8_t end_head;
grub_uint8_t end_sector;
grub_uint8_t end_cylinder;
/* The start sector. Note that this is counted from zero. */
grub_uint32_t start;
/* The length in sector units. */
grub_uint32_t length;
} __attribute__ ((packed));
/* The structure of MBR. */
struct grub_msdos_partition_mbr
{
/* The code area (actually, including BPB). */
grub_uint8_t code[446];
/* Four partition entries. */
struct grub_msdos_partition_entry entries[4];
/* The signature 0xaa55. */
grub_uint16_t signature;
} __attribute__ ((packed));
static inline int
grub_msdos_partition_is_empty (int type)
{
return (type == GRUB_PC_PARTITION_TYPE_NONE);
}
static inline int
grub_msdos_partition_is_extended (int type)
{
return (type == GRUB_PC_PARTITION_TYPE_EXTENDED
|| type == GRUB_PC_PARTITION_TYPE_WIN95_EXTENDED
|| type == GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED);
}
grub_err_t
grub_partition_msdos_iterate (grub_disk_t disk,
int (*hook) (grub_disk_t disk,
const grub_partition_t partition));
#endif /* ! GRUB_PC_PARTITION_HEADER */

View File

@ -0,0 +1,72 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_NET_HEADER
#define GRUB_NET_HEADER 1
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
struct grub_net;
struct grub_net_dev
{
/* The device name. */
const char *name;
/* FIXME: Just a template. */
int (*probe) (struct grub_net *net, const void *addr);
void (*reset) (struct grub_net *net);
int (*poll) (struct grub_net *net);
void (*transmit) (struct grub_net *net, const void *destip,
unsigned srcsock, unsigned destsock, const void *packet);
void (*disable) (struct grub_net *net);
/* The next net device. */
struct grub_net_dev *next;
};
typedef struct grub_net_dev *grub_net_dev_t;
struct grub_fs;
struct grub_net
{
/* The net name. */
const char *name;
/* The underlying disk device. */
grub_net_dev_t dev;
/* The binding filesystem. */
struct grub_fs *fs;
/* FIXME: More data would be required, such as an IP address, a mask,
a gateway, etc. */
/* Device-specific data. */
void *data;
};
typedef struct grub_net *grub_net_t;
/* FIXME: How to abstract networks? More consideration is necessary. */
/* Note: Networks are very different from disks, because networks must
be initialized before used, and the status is persistent. */
#endif /* ! GRUB_NET_HEADER */

View File

@ -0,0 +1,133 @@
/* normal.h - prototypes for the normal mode */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_NORMAL_HEADER
#define GRUB_NORMAL_HEADER 1
#include <grub/term.h>
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/env.h>
#include <grub/menu.h>
#include <grub/command.h>
#include <grub/file.h>
/* The maximum size of a command-line. */
#define GRUB_MAX_CMDLINE 1600
/* The standard left and right margin for some messages. */
#define STANDARD_MARGIN 6
/* The type of a completion item. */
enum grub_completion_type
{
GRUB_COMPLETION_TYPE_COMMAND,
GRUB_COMPLETION_TYPE_DEVICE,
GRUB_COMPLETION_TYPE_PARTITION,
GRUB_COMPLETION_TYPE_FILE,
GRUB_COMPLETION_TYPE_ARGUMENT
};
typedef enum grub_completion_type grub_completion_type_t;
extern struct grub_menu_viewer grub_normal_text_menu_viewer;
extern int grub_normal_exit_level;
/* Defined in `main.c'. */
void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested, int batch);
void grub_menu_init_page (int nested, int edit,
struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term);
char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested);
/* Defined in `cmdline.c'. */
char *grub_cmdline_get (const char *prompt);
grub_err_t grub_set_history (int newsize);
/* Defined in `completion.c'. */
char *grub_normal_do_completion (char *buf, int *restore,
void (*hook) (const char *item, grub_completion_type_t type, int count));
/* Defined in `misc.c'. */
grub_err_t grub_normal_print_device_info (const char *name);
/* Defined in `color.c'. */
char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
/* Defined in `menu_text.c'. */
void grub_wait_after_message (void);
void
grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term);
grub_ssize_t grub_getstringwidth (grub_uint32_t * str,
const grub_uint32_t * last_position,
struct grub_term_output *term);
void grub_print_message_indented (const char *msg, int margin_left,
int margin_right,
struct grub_term_output *term);
void
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
grub_err_t
grub_show_menu (grub_menu_t menu, int nested);
/* Defined in `handler.c'. */
void read_handler_list (void);
void free_handler_list (void);
/* Defined in `dyncmd.c'. */
void read_command_list (const char *prefix);
/* Defined in `autofs.c'. */
void read_fs_list (const char *prefix);
void grub_context_init (void);
void grub_context_fini (void);
void read_crypto_list (const char *prefix);
void read_terminal_list (const char *prefix);
void grub_set_more (int onoff);
void grub_normal_reset_more (void);
void grub_xputs_normal (const char *str);
extern int grub_extractor_level;
grub_err_t
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
const char *users, const char *hotkey,
const char *prefix, const char *sourcecode,
int submenu);
grub_err_t
grub_normal_set_password (const char *user, const char *password);
void grub_normal_free_menu (grub_menu_t menu);
void grub_normal_auth_init (void);
void grub_normal_auth_fini (void);
#endif /* ! GRUB_NORMAL_HEADER */

View File

@ -0,0 +1,183 @@
/* ntfs.h - header for the NTFS filesystem */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_NTFS_H
#define GRUB_NTFS_H 1
#define FILE_MFT 0
#define FILE_MFTMIRR 1
#define FILE_LOGFILE 2
#define FILE_VOLUME 3
#define FILE_ATTRDEF 4
#define FILE_ROOT 5
#define FILE_BITMAP 6
#define FILE_BOOT 7
#define FILE_BADCLUS 8
#define FILE_QUOTA 9
#define FILE_UPCASE 10
#define AT_STANDARD_INFORMATION 0x10
#define AT_ATTRIBUTE_LIST 0x20
#define AT_FILENAME 0x30
#define AT_OBJECT_ID 0x40
#define AT_SECURITY_DESCRIPTOR 0x50
#define AT_VOLUME_NAME 0x60
#define AT_VOLUME_INFORMATION 0x70
#define AT_DATA 0x80
#define AT_INDEX_ROOT 0x90
#define AT_INDEX_ALLOCATION 0xA0
#define AT_BITMAP 0xB0
#define AT_SYMLINK 0xC0
#define AT_EA_INFORMATION 0xD0
#define AT_EA 0xE0
#define ATTR_READ_ONLY 0x1
#define ATTR_HIDDEN 0x2
#define ATTR_SYSTEM 0x4
#define ATTR_ARCHIVE 0x20
#define ATTR_DEVICE 0x40
#define ATTR_NORMAL 0x80
#define ATTR_TEMPORARY 0x100
#define ATTR_SPARSE 0x200
#define ATTR_REPARSE 0x400
#define ATTR_COMPRESSED 0x800
#define ATTR_OFFLINE 0x1000
#define ATTR_NOT_INDEXED 0x2000
#define ATTR_ENCRYPTED 0x4000
#define ATTR_DIRECTORY 0x10000000
#define ATTR_INDEX_VIEW 0x20000000
#define FLAG_COMPRESSED 1
#define FLAG_ENCRYPTED 0x4000
#define FLAG_SPARSE 0x8000
#define BLK_SHR GRUB_DISK_SECTOR_BITS
#define MAX_MFT (1024 >> BLK_SHR)
#define MAX_IDX (16384 >> BLK_SHR)
#define COM_LEN 4096
#define COM_LOG_LEN 12
#define COM_SEC (COM_LEN >> BLK_SHR)
#define AF_ALST 1
#define AF_MMFT 2
#define AF_GPOS 4
#define RF_COMP 1
#define RF_CBLK 2
#define RF_BLNK 4
#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs))
#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t))
#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t))
#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t))
#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t)
#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t)
#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t)
struct grub_ntfs_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint16_t bytes_per_sector;
grub_uint8_t sectors_per_cluster;
grub_uint8_t reserved_1[7];
grub_uint8_t media;
grub_uint16_t reserved_2;
grub_uint16_t sectors_per_track;
grub_uint16_t num_heads;
grub_uint32_t num_hidden_sectors;
grub_uint32_t reserved_3[2];
grub_uint64_t num_total_sectors;
grub_uint64_t mft_lcn;
grub_uint64_t mft_mirr_lcn;
grub_int8_t clusters_per_mft;
grub_int8_t reserved_4[3];
grub_int8_t clusters_per_index;
grub_int8_t reserved_5[3];
grub_uint64_t num_serial;
grub_uint32_t checksum;
} __attribute__ ((packed));
#define grub_ntfs_file grub_fshelp_node
struct grub_ntfs_attr
{
int flags;
char *emft_buf, *edat_buf;
char *attr_cur, *attr_nxt, *attr_end;
grub_uint32_t save_pos;
char *sbuf;
struct grub_ntfs_file *mft;
};
struct grub_fshelp_node
{
struct grub_ntfs_data *data;
char *buf;
grub_uint64_t size;
grub_uint32_t ino;
int inode_read;
struct grub_ntfs_attr attr;
};
struct grub_ntfs_data
{
struct grub_ntfs_file cmft;
struct grub_ntfs_file mmft;
grub_disk_t disk;
grub_uint32_t mft_size;
grub_uint32_t idx_size;
grub_uint32_t spc;
grub_uint32_t blocksize;
grub_uint32_t mft_start;
grub_uint64_t uuid;
};
struct grub_ntfs_comp
{
grub_disk_t disk;
int comp_head, comp_tail;
grub_uint32_t comp_table[16][2];
grub_uint32_t cbuf_ofs, cbuf_vcn, spc;
char *cbuf;
};
struct grub_ntfs_rlst
{
int flags;
grub_disk_addr_t target_vcn, curr_vcn, next_vcn, curr_lcn;
char *cur_run;
struct grub_ntfs_attr *attr;
struct grub_ntfs_comp comp;
};
typedef grub_err_t (*ntfscomp_func_t) (struct grub_ntfs_attr * at, char *dest,
grub_uint32_t ofs, grub_uint32_t len,
struct grub_ntfs_rlst * ctx,
grub_uint32_t vcn);
extern ntfscomp_func_t EXPORT_VAR (grub_ntfscomp_func);
grub_err_t EXPORT_FUNC(grub_ntfs_read_run_list) (struct grub_ntfs_rlst *ctx);
#endif /* ! GRUB_NTFS_H */

View File

@ -0,0 +1,182 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2007,2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OFFSETS_HEADER
#define OFFSETS_HEADER 1
/* The offset of GRUB_TOTAL_MODULE_SIZE. */
#define GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE 0x8
/* The offset of GRUB_KERNEL_IMAGE_SIZE. */
#define GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE 0xc
/* The offset of GRUB_COMPRESSED_SIZE. */
#define GRUB_KERNEL_I386_PC_COMPRESSED_SIZE 0x10
/* The offset of GRUB_INSTALL_DOS_PART. */
#define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x14
/* The offset of GRUB_INSTALL_BSD_PART. */
#define GRUB_KERNEL_I386_PC_INSTALL_BSD_PART 0x18
/* Offset of reed_solomon_redundancy. */
#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x1c
/* The size of the first region which won't be compressed. */
#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xca4
#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x70c
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_I386_PC_PREFIX GRUB_KERNEL_I386_PC_RAW_SIZE
/* End of the data section. */
#define GRUB_KERNEL_I386_PC_PREFIX_END (GRUB_KERNEL_I386_PC_PREFIX + 0x40)
/* The segment where the kernel is loaded. */
#define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800
#define GRUB_KERNEL_I386_PC_LINK_ADDR 0x8200
/* The upper memory area (starting at 640 kiB). */
#define GRUB_MEMORY_I386_PC_UPPER 0xa0000
#define GRUB_MEMORY_I386_QEMU_UPPER GRUB_MEMORY_I386_PC_UPPER
/* The offset of GRUB_CORE_ENTRY_ADDR. */
#define GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR 0x4
/* The offset of GRUB_CORE_ENTRY_ADDR. */
#define GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR 0x8
/* The offset of GRUB_KERNEL_IMAGE_SIZE. */
#define GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE 0xc
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_I386_QEMU_PREFIX 0x10
/* End of the data section. */
#define GRUB_KERNEL_I386_QEMU_PREFIX_END 0x50
#define GRUB_KERNEL_I386_QEMU_LINK_ADDR 0x8200
/* The offset of GRUB_TOTAL_MODULE_SIZE. */
#define GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE 0x8
/* The offset of GRUB_KERNEL_IMAGE_SIZE. */
#define GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE 0xc
/* The offset of GRUB_COMPRESSED_SIZE. */
#define GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE 0x10
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX 0x14
/* End of the data section. */
#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END 0x114
#define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12
#define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400
#define GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE 0
#define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400
#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX 0x4
#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END 0x44
#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4
#define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000
#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ADDR 0x80200000
#define GRUB_KERNEL_MIPS_YEELOONG_LINK_ALIGN 32
#define GRUB_KERNEL_MIPS_YEELOONG_COMPRESSED_SIZE 0x8
#define GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE 0xc
#define GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE 0x08
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX 0x0c
#define GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END 0x54
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_I386_EFI_PREFIX 0x8
/* End of the data section. */
#define GRUB_KERNEL_I386_EFI_PREFIX_END 0x50
/* The offset of GRUB_PREFIX. */
#define GRUB_KERNEL_X86_64_EFI_PREFIX 0x8
/* End of the data section. */
#define GRUB_KERNEL_X86_64_EFI_PREFIX_END 0x50
#define GRUB_KERNEL_I386_COREBOOT_PREFIX 0x2
#define GRUB_KERNEL_I386_COREBOOT_PREFIX_END 0x42
#define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR 0x8200
#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX GRUB_KERNEL_I386_COREBOOT_PREFIX
#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END GRUB_KERNEL_I386_COREBOOT_PREFIX_END
#define GRUB_KERNEL_I386_IEEE1275_PREFIX 0x2
#define GRUB_KERNEL_I386_IEEE1275_PREFIX_END 0x42
#define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR 0x10000
#define GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN 0x1000
#define GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN 0x1
#define GRUB_KERNEL_I386_MULTIBOOT_MOD_ALIGN GRUB_KERNEL_I386_COREBOOT_MOD_ALIGN
/* Non-zero value is only needed for PowerMacs. */
#define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0
#define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0
#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000
#define GRUB_KERNEL_MIPS_YEELOONG_MOD_ALIGN 0x1
/* Minimal gap between _end and the start of the modules. It's a hack
for PowerMac to prevent "CLAIM failed" error. The real fix is to
rewrite grub-mkimage to generate valid ELF files. */
#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000
#ifdef GRUB_MACHINE
#define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c
#define GRUB_OFFSETS_CONCAT(a,b,c) GRUB_OFFSETS_CONCAT_(a,b,c)
#define GRUB_KERNEL_MACHINE_MOD_ALIGN GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_ALIGN)
#define GRUB_KERNEL_MACHINE_MOD_GAP GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_GAP)
#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _TOTAL_MODULE_SIZE)
#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE)
#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE)
#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE)
#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX)
#define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END)
#define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG)
#define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER)
#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE)
#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART)
#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART)
#endif
#ifndef ASM_FILE
struct grub_pc_bios_boot_blocklist
{
grub_uint64_t start;
grub_uint16_t len;
grub_uint16_t segment;
} __attribute__ ((packed));
#endif
#endif

View File

@ -0,0 +1,91 @@
/* parser.h - prototypes for the command line parser. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2007,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PARSER_HEADER
#define GRUB_PARSER_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
#include <grub/reader.h>
/* All the states for the command line. */
typedef enum
{
GRUB_PARSER_STATE_TEXT = 1,
GRUB_PARSER_STATE_ESC,
GRUB_PARSER_STATE_QUOTE,
GRUB_PARSER_STATE_DQUOTE,
GRUB_PARSER_STATE_VAR,
GRUB_PARSER_STATE_VARNAME,
GRUB_PARSER_STATE_VARNAME2,
GRUB_PARSER_STATE_QVAR,
GRUB_PARSER_STATE_QVARNAME,
GRUB_PARSER_STATE_QVARNAME2
} grub_parser_state_t;
/* A single state transition. */
struct grub_parser_state_transition
{
/* The state that is looked up. */
grub_parser_state_t from_state;
/* The next state, determined by FROM_STATE and INPUT. */
grub_parser_state_t to_state;
/* The input that will determine the next state from FROM_STATE. */
char input;
/* If set to 1, the input is valid and should be used. */
int keep_value;
};
/* Determines the state following STATE, determined by C. */
grub_parser_state_t
EXPORT_FUNC (grub_parser_cmdline_state) (grub_parser_state_t state,
char c, char *result);
grub_err_t
EXPORT_FUNC (grub_parser_split_cmdline) (const char *cmdline,
grub_reader_getline_t getline,
int *argc, char ***argv);
struct grub_parser
{
/* The next parser. */
struct grub_parser *next;
/* The parser name. */
const char *name;
/* Initialize the parser. */
grub_err_t (*init) (void);
/* Clean up the parser. */
grub_err_t (*fini) (void);
grub_err_t (*parse_line) (char *line, grub_reader_getline_t getline);
};
typedef struct grub_parser *grub_parser_t;
grub_err_t grub_parser_execute (char *source);
grub_err_t
grub_rescue_parse_line (char *line, grub_reader_getline_t getline);
#endif /* ! GRUB_PARSER_HEADER */

View File

@ -0,0 +1,134 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2004,2006,2007 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PART_HEADER
#define GRUB_PART_HEADER 1
#include <grub/dl.h>
#include <grub/list.h>
struct grub_disk;
typedef struct grub_partition *grub_partition_t;
#ifdef GRUB_UTIL
typedef enum
{
GRUB_EMBED_PCBIOS
} grub_embed_type_t;
#endif
/* Partition map type. */
struct grub_partition_map
{
/* The next partition map type. */
struct grub_partition_map *next;
/* The name of the partition map type. */
const char *name;
/* Call HOOK with each partition, until HOOK returns non-zero. */
grub_err_t (*iterate) (struct grub_disk *disk,
int (*hook) (struct grub_disk *disk,
const grub_partition_t partition));
#ifdef GRUB_UTIL
/* Determine sectors available for embedding. */
grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors,
grub_embed_type_t embed_type,
grub_disk_addr_t **sectors);
#endif
};
typedef struct grub_partition_map *grub_partition_map_t;
/* Partition description. */
struct grub_partition
{
/* The partition number. */
int number;
/* The start sector (relative to parent). */
grub_disk_addr_t start;
/* The length in sector units. */
grub_uint64_t len;
/* The offset of the partition table. */
grub_disk_addr_t offset;
/* The index of this partition in the partition table. */
int index;
/* Parent partition (physically contains this partition). */
struct grub_partition *parent;
/* The type partition map. */
grub_partition_map_t partmap;
/* The type of partition whne it's on MSDOS.
Used for embedding detection. */
grub_uint8_t msdostype;
};
grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,
const char *str);
int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk,
int (*hook) (struct grub_disk *disk,
const grub_partition_t partition));
char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition);
extern grub_partition_map_t EXPORT_VAR(grub_partition_map_list);
#ifndef GRUB_LST_GENERATOR
static inline void
grub_partition_map_register (grub_partition_map_t partmap)
{
grub_list_push (GRUB_AS_LIST_P (&grub_partition_map_list),
GRUB_AS_LIST (partmap));
}
#endif
static inline void
grub_partition_map_unregister (grub_partition_map_t partmap)
{
grub_list_remove (GRUB_AS_LIST_P (&grub_partition_map_list),
GRUB_AS_LIST (partmap));
}
#define FOR_PARTITION_MAPS(var) FOR_LIST_ELEMENTS((var), (grub_partition_map_list))
static inline grub_disk_addr_t
grub_partition_get_start (const grub_partition_t p)
{
grub_partition_t part;
grub_uint64_t part_start = 0;
for (part = p; part; part = part->parent)
part_start += part->start;
return part_start;
}
static inline grub_uint64_t
grub_partition_get_len (const grub_partition_t p)
{
return p->len;
}
#endif /* ! GRUB_PART_HEADER */

View File

@ -0,0 +1,58 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PARTTOOL_HEADER
#define GRUB_PARTTOOL_HEADER 1
struct grub_parttool_argdesc
{
char *name;
char *desc;
enum {GRUB_PARTTOOL_ARG_END, GRUB_PARTTOOL_ARG_BOOL, GRUB_PARTTOOL_ARG_VAL}
type;
};
struct grub_parttool_args
{
int set;
union
{
int bool;
char *str;
};
};
typedef grub_err_t (*grub_parttool_function_t) (const grub_device_t dev,
const struct grub_parttool_args *args);
struct grub_parttool
{
struct grub_parttool *next;
char *name;
int handle;
int nargs;
struct grub_parttool_argdesc *args;
grub_parttool_function_t func;
};
int grub_parttool_register(const char *part_name,
const grub_parttool_function_t func,
const struct grub_parttool_argdesc *args);
void grub_parttool_unregister (int handle);
#endif /* ! GRUB_PARTTOOL_HEADER*/

View File

@ -0,0 +1,137 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PCI_H
#define GRUB_PCI_H 1
#ifndef ASM_FILE
#include <grub/types.h>
#include <grub/symbol.h>
#endif
#define GRUB_PCI_ADDR_SPACE_MASK 0x01
#define GRUB_PCI_ADDR_SPACE_MEMORY 0x00
#define GRUB_PCI_ADDR_SPACE_IO 0x01
#define GRUB_PCI_ADDR_MEM_TYPE_MASK 0x06
#define GRUB_PCI_ADDR_MEM_TYPE_32 0x00 /* 32 bit address */
#define GRUB_PCI_ADDR_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
#define GRUB_PCI_ADDR_MEM_TYPE_64 0x04 /* 64 bit address */
#define GRUB_PCI_ADDR_MEM_PREFETCH 0x08 /* prefetchable */
#define GRUB_PCI_ADDR_MEM_MASK ~0xf
#define GRUB_PCI_ADDR_IO_MASK ~0x03
#define GRUB_PCI_REG_PCI_ID 0x00
#define GRUB_PCI_REG_VENDOR 0x00
#define GRUB_PCI_REG_DEVICE 0x02
#define GRUB_PCI_REG_COMMAND 0x04
#define GRUB_PCI_REG_STATUS 0x06
#define GRUB_PCI_REG_REVISION 0x08
#define GRUB_PCI_REG_CLASS 0x08
#define GRUB_PCI_REG_CACHELINE 0x0c
#define GRUB_PCI_REG_LAT_TIMER 0x0d
#define GRUB_PCI_REG_HEADER_TYPE 0x0e
#define GRUB_PCI_REG_BIST 0x0f
#define GRUB_PCI_REG_ADDRESSES 0x10
/* Beware that 64-bit address takes 2 registers. */
#define GRUB_PCI_REG_ADDRESS_REG0 0x10
#define GRUB_PCI_REG_ADDRESS_REG1 0x14
#define GRUB_PCI_REG_ADDRESS_REG2 0x18
#define GRUB_PCI_REG_ADDRESS_REG3 0x1c
#define GRUB_PCI_REG_ADDRESS_REG4 0x20
#define GRUB_PCI_REG_ADDRESS_REG5 0x24
#define GRUB_PCI_REG_CIS_POINTER 0x28
#define GRUB_PCI_REG_SUBVENDOR 0x2c
#define GRUB_PCI_REG_SUBSYSTEM 0x2e
#define GRUB_PCI_REG_ROM_ADDRESS 0x30
#define GRUB_PCI_REG_CAP_POINTER 0x34
#define GRUB_PCI_REG_IRQ_LINE 0x3c
#define GRUB_PCI_REG_IRQ_PIN 0x3d
#define GRUB_PCI_REG_MIN_GNT 0x3e
#define GRUB_PCI_REG_MAX_LAT 0x3f
#define GRUB_PCI_COMMAND_IO_ENABLED 0x0001
#define GRUB_PCI_COMMAND_MEM_ENABLED 0x0002
#define GRUB_PCI_COMMAND_BUS_MASTER 0x0004
#define GRUB_PCI_COMMAND_PARITY_ERROR 0x0040
#define GRUB_PCI_COMMAND_SERR_ENABLE 0x0100
#define GRUB_PCI_STATUS_CAPABILITIES 0x0010
#define GRUB_PCI_STATUS_66MHZ_CAPABLE 0x0020
#define GRUB_PCI_STATUS_FAST_B2B_CAPABLE 0x0080
#define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9
#define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600
#define GRUB_PCI_CLASS_SUBCLASS_VGA 0x0300
#ifndef ASM_FILE
typedef grub_uint32_t grub_pci_id_t;
#ifdef GRUB_MACHINE_EMU
#include <grub/pciutils.h>
#else
typedef grub_uint32_t grub_pci_address_t;
struct grub_pci_device
{
int bus;
int device;
int function;
};
typedef struct grub_pci_device grub_pci_device_t;
static inline int
grub_pci_get_bus (grub_pci_device_t dev)
{
return dev.bus;
}
static inline int
grub_pci_get_device (grub_pci_device_t dev)
{
return dev.device;
}
static inline int
grub_pci_get_function (grub_pci_device_t dev)
{
return dev.function;
}
#include <grub/cpu/pci.h>
#endif
typedef int NESTED_FUNC_ATTR (*grub_pci_iteratefunc_t)
(grub_pci_device_t dev, grub_pci_id_t pciid);
grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev,
int reg);
void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook);
struct grub_pci_dma_chunk;
struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align,
grub_size_t size);
void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch);
volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch);
grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch);
#endif
#endif /* GRUB_PCI_H */

View File

@ -0,0 +1,103 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_PCIUTILS_H
#define GRUB_PCIUTILS_H 1
#include <pciaccess.h>
typedef struct pci_device *grub_pci_device_t;
static inline int
grub_pci_get_bus (grub_pci_device_t dev)
{
return dev->bus;
}
static inline int
grub_pci_get_device (grub_pci_device_t dev)
{
return dev->dev;
}
static inline int
grub_pci_get_function (grub_pci_device_t dev)
{
return dev->func;
}
struct grub_pci_address
{
grub_pci_device_t dev;
int pos;
};
typedef struct grub_pci_address grub_pci_address_t;
static inline grub_uint32_t
grub_pci_read (grub_pci_address_t addr)
{
grub_uint32_t ret;
pci_device_cfg_read_u32 (addr.dev, &ret, addr.pos);
return ret;
}
static inline grub_uint16_t
grub_pci_read_word (grub_pci_address_t addr)
{
grub_uint16_t ret;
pci_device_cfg_read_u16 (addr.dev, &ret, addr.pos);
return ret;
}
static inline grub_uint8_t
grub_pci_read_byte (grub_pci_address_t addr)
{
grub_uint8_t ret;
pci_device_cfg_read_u8 (addr.dev, &ret, addr.pos);
return ret;
}
static inline void
grub_pci_write (grub_pci_address_t addr, grub_uint32_t data)
{
pci_device_cfg_write_u32 (addr.dev, data, addr.pos);
}
static inline void
grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data)
{
pci_device_cfg_write_u16 (addr.dev, data, addr.pos);
}
static inline void
grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data)
{
pci_device_cfg_write_u8 (addr.dev, data, addr.pos);
}
void *
grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base,
grub_size_t size);
void
grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem,
grub_size_t size);
#endif /* GRUB_PCIUTILS_H */

View File

@ -0,0 +1,96 @@
/* raid.h - On disk structures for RAID. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_RAID_H
#define GRUB_RAID_H 1
#include <grub/types.h>
#define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0
#define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1
#define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2
#define GRUB_RAID_LAYOUT_RIGHT_SYMMETRIC 3
#define GRUB_RAID_LAYOUT_RIGHT_MASK 1
#define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2
struct grub_raid_member
{
grub_disk_t device; /* Array of total_devs devices. */
grub_disk_addr_t start_sector;
/* Start of each device, in 512 byte sectors. */
};
struct grub_raid_array
{
int number; /* The device number, taken from md_minor so we
are consistent with the device name in
Linux. */
int level; /* RAID levels, only 0, 1 or 5 at the moment. */
int layout; /* Layout for RAID 5/6. */
unsigned int total_devs; /* Total number of devices in the array. */
grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */
grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte
sectors. */
unsigned int index; /* Index of current device. */
int uuid_len; /* The length of uuid. */
char *uuid; /* The UUID of the device. */
/* The following field is setup by the caller. */
char *name; /* That will be "md<number>". */
unsigned int nr_devs; /* The number of devices we've found so far. */
unsigned int allocated_devs;
struct grub_raid_member *members;
struct grub_raid_array *next;
#ifdef GRUB_UTIL
struct grub_raid *driver;
#endif
};
struct grub_raid
{
const char *name;
grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector);
struct grub_raid *next;
};
typedef struct grub_raid *grub_raid_t;
void grub_raid_register (grub_raid_t raid);
void grub_raid_unregister (grub_raid_t raid);
void grub_raid_block_xor (char *buf1, const char *buf2, int size);
typedef grub_err_t (*grub_raid5_recover_func_t) (struct grub_raid_array *array,
int disknr, char *buf,
grub_disk_addr_t sector,
int size);
typedef grub_err_t (*grub_raid6_recover_func_t) (struct grub_raid_array *array,
int disknr, int p, char *buf,
grub_disk_addr_t sector,
int size);
extern grub_raid5_recover_func_t grub_raid5_recover_func;
extern grub_raid6_recover_func_t grub_raid6_recover_func;
#endif /* ! GRUB_RAID_H */

View File

@ -0,0 +1,29 @@
/* reader.h - prototypes for command line reader. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_READER_HEADER
#define GRUB_READER_HEADER 1
#include <grub/err.h>
typedef grub_err_t (*grub_reader_getline_t) (char **, int);
void grub_rescue_run (void);
#endif /* ! GRUB_READER_HEADER */

View File

@ -0,0 +1,30 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_REED_SOLOMON_HEADER
#define GRUB_REED_SOLOMON_HEADER 1
void
grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size,
grub_size_t redundancy);
void
grub_reed_solomon_recover (void *buffer, grub_size_t data_size,
grub_size_t redundancy);
#endif

Some files were not shown because too many files have changed in this diff Show More