1N/A * GRUB -- GRand Unified Bootloader 1N/A * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. 1N/A * This program is free software; you can redistribute it and/or modify 1N/A * it under the terms of the GNU General Public License as published by 1N/A * the Free Software Foundation; either version 2 of the License, or 1N/A * (at your option) any later version. 1N/A * This program is distributed in the hope that it will be useful, 1N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of 1N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A * GNU General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program; if not, write to the Free Software 1N/A * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. 1N/A * The zfs plug-in routines for GRUB are: 1N/A * zfs_mount() - locates a valid uberblock of the root pool and reads 1N/A * in its MOS at the memory address MOS. 1N/A * zfs_open() - locates a plain file object by following the MOS 1N/A * and places its dnode at the memory address DNODE. 1N/A * zfs_read() - read in the data blocks pointed by the DNODE. 1N/A * ZFS_SCRATCH is used as a working area. 1N/A * (memory addr) MOS DNODE ZFS_SCRATCH 1N/A * +-------V---------V----------V---------------+ 1N/A * memory | | dnode | dnode | scratch | 1N/A * | | 512B | 512B | area | 1N/A * +--------------------------------------------+ 1N/A/* cache for a file block of the currently zfs_open()-ed file */ 1N/A/* cache for a dnode block */ 1N/A {
"inherit", 0},
/* ZIO_COMPRESS_INHERIT */ 1N/A {
"off", 0},
/* ZIO_COMPRESS_OFF */ 1N/A {
"empty", 0}
/* ZIO_COMPRESS_EMPTY */ 1N/A * Our own version of bcmp(). 1N/A * Our own version of log2(). Same thing as highbit()-1. 1N/A/* Checksum Functions */ 1N/A/* Checksum Table and Values */ 1N/A * zio_checksum_verify: Provides support for checksum verification. 1N/A * Fletcher2, Fletcher4, and SHA256 are supported. 1N/A /* byteswap is not supported */ 1N/A * vdev_label_start returns the physical disk offset (in bytes) of 1N/A * vdev_uberblock_compare takes two uberblock structures and returns an integer 1N/A * indicating the more recent of the two. 1N/A * Return Value = 1 if ub2 is more recent 1N/A * Return Value = -1 if ub1 is more recent 1N/A * The most recent uberblock is determined using its transaction number and 1N/A * timestamp. The uberblock with the highest transaction number is 1N/A * considered "newer". If the transaction numbers of the two blocks match, the 1N/A * timestamps are compared to determine the "newer" of the two. 1N/A * Three pieces of information are needed to verify an uberblock: the magic 1N/A * number, the version number, and the checksum. 1N/A * Currently Implemented: version number, magic number 1N/A * Need to Implement: checksum 1N/A * Find the best uberblock. 1N/A * Success - Pointer to the best uberblock. 1N/A * Read a block of data based on the gang block address dva, 1N/A * and put its data in buf. 1N/A /* pick a good dva from the block pointer */ 1N/A * Read gang block header, verify its checksum, loop through all gang blocks 1N/A * to collect its data based on the gang block address dva and put it in buf. 1N/A /* read in the gang block header */ 1N/A /* self checksuming the gang block header */ 1N/A * Read in a block of raw data to buf. 1N/A /* Only one top-level vdev is supported in the root pool */ 1N/A /* read in a data block */ 1N/A * Loop through DVAs to read in a block of raw data to buf and verify the 1N/A /* pick a good dva from the block pointer */ 1N/A /* if no errors, return from here */ 1N/A * Read in a block of data, verify its checksum, decompress if needed, 1N/A * and put the uncompressed data in buf. 1N/A * Get the block from a block id. 1N/A * push the block onto the stack. 1N/A * mzap_lookup: Looks up property described by "name" and returns the value 1N/A for (i = 0; i <
256; i++) {
1N/A * Only use 28 bits, since we need 4 bits in the cookie for the 1N/A * collision differentiator. We MUST use the high bits, since 1N/A * those are the onces that we first pay attention to when 1N/A * chosing the bucket. 1N/A crc &= ~((
1ULL << (
64 -
28)) -
1);
1N/A * Only to be used on 8-bit arrays. 1N/A * array_len is actual len in bytes (not encoded le_value_length). 1N/A * buf is null-terminated. 1N/A * Given a zap_leaf_phys_t, walk thru the zap leaf chunks to get the 1N/A * value for the property "name". 1N/A /* Verify if this is a valid leaf block */ 1N/A /* Verify the chunk entry */ 1N/A /* get the uint64_t property value */ 1N/A /* Verify if this is a fat zap header block */ 1N/A /* get block id from index */ 1N/A /* external pointer tables not supported */ 1N/A /* Get the leaf block */ 1N/A * Read in the data of a zap object and find the value for a matching 1N/A /* Read in the first block of the zap object data. */ 1N/A /* this is a fat zap */ 1N/A * Get the dnode of an object number from the metadnode of an object set. 1N/A * mdn - metadnode to get the object dnode 1N/A * objnum - object number for the object dnode 1N/A * buf - data buffer that holds the returning dnode 1N/A * stack - scratch area 1N/A int epbs;
/* shift of number of dnodes in a block */ 1N/A int idx;
/* index within a block */ 1N/A * Check if this is a special file that resides at the top 1N/A * dataset of the pool. Currently this is the GRUB menu, 1N/A * boot signature and boot signature backup. 1N/A * str starts with '/'. 1N/A * Get the file dnode for a given file name where mdn is the meta dnode 1N/A * for this ZFS object set. When found, place the file dnode in dn. 1N/A * The 'path' argument will be mangled. 1N/A /* skip leading slashes */ 1N/A /* get the next component name */ 1N/A *
path = 0;
/* ensure null termination */ 1N/A /* We found the dnode for this file. Verify if it is a plain file. */ 1N/A * Get the default 'bootfs' property value from the rootpool. 1N/A * find the object number for 'pool_props', and get the dnode 1N/A * of the 'pool_props'. 1N/A * Given a MOS metadnode, get the metadnode of a given filesystem name (fsname), 1N/A * e.g. pool/rootfs, or a given object number (obj), e.g. the object number 1N/A * If no fsname and no obj are given, return the DSL_DIR metadnode. 1N/A * If fsname is given, return its metadnode and its matching object number. 1N/A * If only obj is given, return the metadnode for this object number. 1N/A /* take out the pool name */ 1N/A * For a given XDR packed nvlist, verify the first 4 bytes and move on. 1N/A * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : 1N/A * nvl_version (4 bytes) 1N/A * nvl_nvflag (4 bytes) 1N/A * encoded size of the nvpair (4 bytes) 1N/A * decoded size of the nvpair (4 bytes) 1N/A * name string size (4 bytes) 1N/A * name string data (sizeof(NV_ALIGN4(string)) 1N/A * data type (4 bytes) 1N/A * # of elements in the nvpair (4 bytes) 1N/A * 2 zero's for the last nvpair 1N/A * (end of the entire list) (8 bytes) 1N/A /* Verify if the 1st and 2nd byte in the nvlist are valid. */ 1N/A /* skip the header, nvl_version, and nvl_nvflag */ 1N/A /* skip the header, nvl_version, and nvl_nvflag */ 1N/A * Loop thru the nvpair list 1N/A * The XDR representation of an integer is in big-endian byte order. 1N/A * Check if this vdev is online and is in a good state. 1N/A * The caller should already allocate MAXPATHLEN memory for bootpath and devid. 1N/A /* for a spare vdev, pick the disk labeled with "is_spare" */ 1N/A * Check the disk label information and retrieve needed vdev name-value pairs. 1N/A /* Read in the vdev name-value pair list (112K). */ 1N/A /* not an active device */ 1N/A * zfs_mount() locates a valid uberblock of the root pool and read in its MOS 1N/A * to the memory address MOS. 1N/A /* if it's our first time here, zero the best uberblock out */ 1N/A * some eltorito stacks don't give us a size and 1N/A * we end up setting the size to MAXUINT, further 1N/A * some of these devices stop working once a single 1N/A * read past the end has been issued. Checking 1N/A * for a maximum part_length and skipping the backup 1N/A * avoids breaking down on such devices. 1N/A /* Read in the uberblock ring (128K). */ 1N/A /* Got the MOS. Save it at the memory addr MOS. */ 1N/A * While some fs impls. (tftp) rely on setting and keeping 1N/A * global errnums set, others won't reset it and will break 1N/A * when issuing rawreads. The goal here is to simply not 1N/A * have zfs mount attempts impact the previous state. 1N/A * zfs_open() locates a file in the rootpool by following the 1N/A * MOS and places the dnode of the file in the memory address DNODE. 1N/A * menu.lst is placed at the root pool filesystem level, 1N/A * do not goto 'current_bootfs'. 1N/A /* Get the default root filesystem object number */ 1N/A /* get the file size and set the file position to 0 */ 1N/A * For DMU_OT_SA we will need to locate the SIZE attribute 1N/A * attribute, which could be either in the bonus buffer 1N/A * or the "spill" block. 1N/A /* reset errnum to rawread() failure */ 1N/A * zfs_read reads in the data blocks pointed by the DNODE. 1N/A * len - the length successfully read in to the buffer 1N/A * If offset is in memory, move it into the buffer provided and return. 1N/A * Entire Dnode is too big to fit into the space available. We 1N/A * will need to read it in chunks. This could be optimized to 1N/A * read in as large a chunk as there is space available, but for 1N/A * now, this only reads in one data block at a time. 1N/A * Find requested blkid and the offset within that block. 1N/A#
endif /* FSYS_ZFS */