15b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
25b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GRUB  --  GRand Unified Bootloader
35b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
45b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Copyright (c) 2004  Valery Hromov
55b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
65b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
75b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  it under the terms of the GNU General Public License as published by
85b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
95b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  (at your option) any later version.
105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  This program is distributed in the hope that it will be useful,
125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  GNU General Public License for more details.
155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  You should have received a copy of the GNU General Public License
175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  along with this program; if not, write to the Free Software
185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Elements of this file were originally from the FreeBSD "biosboot"
235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * bootloader file "disk.c" dated 4/12/95.
245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * The license and header comments from that file are included here.
265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/*
295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Mach Operating System
305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Copyright (c) 1992, 1991 Carnegie Mellon University
315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * All Rights Reserved.
325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Permission to use, copy, modify and distribute this software and its
345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * documentation is hereby granted, provided that both the copyright
355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * notice and this permission notice appear in all copies of the
365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * software, derivative works or modified versions, and any portions
375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * thereof, and that both notices appear in supporting documentation.
385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * Carnegie Mellon requests users of this software to return to
445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  School of Computer Science
475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Carnegie Mellon University
485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *  Pittsburgh PA 15213-3890
495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * any improvements or extensions that they make and grant Carnegie Mellon
515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project * the rights to redistribute these changes.
525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *
535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	from: Mach, Revision 2.2  92/04/04  11:35:49  rpd
545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project *	$Id: fsys_ufs2.c,v 1.2 2004/06/19 12:17:52 okuji Exp $
555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project */
565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifdef FSYS_UFS2
585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "shared.h"
605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "filesys.h"
615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#include "ufs2.h"
635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* used for filesystem map blocks */
655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mapblock;
665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mapblock_offset;
675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int mapblock_bsize;
685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int sblock_try[] = SBLOCKSEARCH;
705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic ufs2_daddr_t sblockloc;
715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic int type;
725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* pointer to superblock */
745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define SUPERBLOCK ((struct fs *) ( FSYS_BUF + 8192 ))
755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define INODE_UFS2 ((struct ufs2_dinode *) ( FSYS_BUF + 16384 ))
775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MAPBUF ( FSYS_BUF + 24576 )
795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#define MAPBUF_LEN 8192
805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectufs2_mount (void)
835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int retval = 0;
855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int i;
865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  sblockloc = -1;
885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  type = 0;
895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (! (((current_drive & 0x80) || (current_slice != 0))
915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	 && ! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_BSDFFS)))
925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      for (i = 0; sblock_try[i] != -1; ++i)
945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE))
965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		 || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK)))
975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      if (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC /* &&
995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project							   (SUPERBLOCK->fs_sblockloc == sblockloc ||
1005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project						     (SUPERBLOCK->fs_old_flags & FS_FLAGS_UPDATED) == 0)*/)
1015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
1025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  type = 2;
1035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      else
1055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		{
1065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		  continue;
1075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		}
1085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      retval = 1;
1105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      sblockloc = sblock_try[i];
1115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      break;
1125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
1135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock = -1;
1175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  mapblock_offset = -1;
1185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return retval;
1205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectstatic grub_int64_t
1235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectblock_map (int file_block)
1245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int bnum, offset, bsize;
1265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (file_block < NDADDR)
1285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return (INODE_UFS2->di_db[file_block]);
1295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* If the blockmap loaded does not include FILE_BLOCK,
1315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     load a new blockmap.  */
1325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if ((bnum = fsbtodb (SUPERBLOCK, INODE_UFS2->di_ib[0])) != mapblock
1345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      || (mapblock_offset <= bnum && bnum <= mapblock_offset + mapblock_bsize))
1355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (MAPBUF_LEN < SUPERBLOCK->fs_bsize)
1375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  offset = ((file_block - NDADDR) % NINDIR (SUPERBLOCK));
1395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bsize = MAPBUF_LEN;
1405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (offset + MAPBUF_LEN > SUPERBLOCK->fs_bsize)
1425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    offset = (SUPERBLOCK->fs_bsize - MAPBUF_LEN) / sizeof (int);
1435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      else
1455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  bsize = SUPERBLOCK->fs_bsize;
1475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  offset = 0;
1485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (! devread (bnum, offset * sizeof (int), bsize, (char *) MAPBUF))
1515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
1525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mapblock = -1;
1535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mapblock_bsize = -1;
1545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  mapblock_offset = -1;
1555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FSYS_CORRUPT;
1565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return -1;
1575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
1585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock = bnum;
1605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock_bsize = bsize;
1615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      mapblock_offset = offset;
1625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return (((grub_int64_t *) MAPBUF)[((file_block - NDADDR) % NINDIR (SUPERBLOCK))
1655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project				    - mapblock_offset]);
1665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
1675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
1695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectufs2_read (char *buf, int len)
1705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
1715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int logno, off, size, ret = 0;
1725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_int64_t map;
1735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (len && !errnum)
1755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
1765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      off = blkoff (SUPERBLOCK, filepos);
1775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      logno = lblkno (SUPERBLOCK, filepos);
1785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size = blksize (SUPERBLOCK, INODE_UFS2, logno);
1795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if ((map = block_map (logno)) < 0)
1815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	break;
1825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      size -= off;
1845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (size > len)
1865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	size = len;
1875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      disk_read_func = disk_read_hook;
1895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      devread (fsbtodb (SUPERBLOCK, map), off, size, buf);
1915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      disk_read_func = NULL;
1935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
1945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      buf += size;
1955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      len -= size;
1965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filepos += size;
1975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      ret += size;
1985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
1995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (errnum)
2015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    ret = 0;
2025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return ret;
2045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
2055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
2075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectufs2_dir (char *dirname)
2085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
2095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  char *rest, ch;
2105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  int block, off, loc, ino = ROOTINO;
2115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  grub_int64_t map;
2125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  struct direct *dp;
2135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project/* main loop to find destination inode */
2155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectloop:
2165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* load current inode (defaults to the root inode) */
2185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    if (!devread (fsbtodb (SUPERBLOCK, ino_to_fsba (SUPERBLOCK, ino)),
2205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    ino % (SUPERBLOCK->fs_inopb) * sizeof (struct ufs2_dinode),
2215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    sizeof (struct ufs2_dinode), (char *) INODE_UFS2))
2225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project		    return 0;			/* XXX what return value? */
2235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* if we have a real file (and we're not just printing possibilities),
2255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     then this is where we want to exit */
2265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!*dirname || isspace (*dirname))
2285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if ((INODE_UFS2->di_mode & IFMT) != IFREG)
2305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_BAD_FILETYPE;
2325b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
2335b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2345b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2355b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      filemax = INODE_UFS2->di_size;
2365b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2375b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      /* incomplete implementation requires this! */
2385b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize;
2395b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 1;
2405b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2415b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2425b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* continue with file/directory name interpretation */
2435b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2445b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (*dirname == '/')
2455b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    dirname++;
2465b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2475b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (!(INODE_UFS2->di_size) || ((INODE_UFS2->di_mode & IFMT) != IFDIR))
2485b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2495b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      errnum = ERR_BAD_FILETYPE;
2505b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      return 0;
2515b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
2525b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2535b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++);
2545b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2555b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  *rest = 0;
2565b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  loc = 0;
2575b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2585b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* loop for reading a the entries in a directory */
2595b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2605b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  do
2615b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    {
2625b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (loc >= INODE_UFS2->di_size)
2635b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2645b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (print_possibilities < 0)
2655b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    return 1;
2665b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2675b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  errnum = ERR_FILE_NOT_FOUND;
2685b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  *rest = ch;
2695b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  return 0;
2705b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2715b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2725b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (!(off = blkoff (SUPERBLOCK, loc)))
2735b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2745b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  block = lblkno (SUPERBLOCK, loc);
2755b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2765b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if ((map = block_map (block)) < 0
2775b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      || !devread (fsbtodb (SUPERBLOCK, map), 0,
2785b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			   blksize (SUPERBLOCK, INODE_UFS2, block),
2795b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			   (char *) FSYS_BUF))
2805b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    {
2815b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      errnum = ERR_FSYS_CORRUPT;
2825b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      *rest = ch;
2835b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	      return 0;
2845b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    }
2855b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2865b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2875b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      dp = (struct direct *) (FSYS_BUF + off);
2885b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      loc += dp->d_reclen;
2895b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2905b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#ifndef STAGE1_5
2915b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project      if (dp->d_ino && print_possibilities && ch != '/'
2925b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  && (!*dirname || substring (dirname, dp->d_name) <= 0))
2935b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	{
2945b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  if (print_possibilities > 0)
2955b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	    print_possibilities = -print_possibilities;
2965b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
2975b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	  print_a_completion (dp->d_name);
2985b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project	}
2995b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* STAGE1_5 */
3005b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    }
3015b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  while (!dp->d_ino || (substring (dirname, dp->d_name) != 0
3025b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project			|| (print_possibilities && ch != '/')));
3035b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3045b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* only get here if we have a matching directory entry */
3055b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3065b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  ino = dp->d_ino;
3075b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  *(dirname = rest) = ch;
3085b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3095b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* go back to main loop at top of function */
3105b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  goto loop;
3115b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3125b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3135b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectint
3145b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Projectufs2_embed (int *start_sector, int needed_sectors)
3155b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project{
3165b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* XXX: I don't know if this is really correct. Someone who is
3175b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     familiar with BSD should check for this.  */
3185b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  if (needed_sectors > 14)
3195b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project    return 0;
3205b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3215b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  *start_sector = 1;
3225b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#if 1
3235b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  /* FIXME: Disable the embedding in FFS until someone checks if
3245b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project     the code above is correct.  */
3255b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 0;
3265b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#else
3275b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project  return 1;
3285b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif
3295b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project}
3305b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project
3315b1eb061628a97aae48a9c0bcaa96eb0bfa07aa4The Android Open Source Project#endif /* FSYS_UFS2 */
332