Print this page
    
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/boot/lib/libstand/ufs.c
          +++ new/usr/src/boot/lib/libstand/ufs.c
   1    1  /*      $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $    */
   2    2  
   3      -/*-
        3 +/*
   4    4   * Copyright (c) 2002 Networks Associates Technology, Inc.
   5    5   * All rights reserved.
   6    6   *
   7    7   * This software was developed for the FreeBSD Project by Marshall
   8    8   * Kirk McKusick and Network Associates Laboratories, the Security
   9    9   * Research Division of Network Associates, Inc. under DARPA/SPAWAR
  10   10   * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
  11   11   * research program
  12   12   *
  13   13   * Copyright (c) 1982, 1989, 1993
  14   14   *      The Regents of the University of California.  All rights reserved.
  15   15   *
  16   16   * This code is derived from software contributed to Berkeley by
  17   17   * The Mach Operating System project at Carnegie-Mellon University.
  18   18   *
  19   19   * Redistribution and use in source and binary forms, with or without
  20   20   * modification, are permitted provided that the following conditions
  21   21   * are met:
  22   22   * 1. Redistributions of source code must retain the above copyright
  23   23   *    notice, this list of conditions and the following disclaimer.
  24   24   * 2. Redistributions in binary form must reproduce the above copyright
  25   25   *    notice, this list of conditions and the following disclaimer in the
  26   26   *    documentation and/or other materials provided with the distribution.
  27   27   * 3. Neither the name of the University nor the names of its contributors
  28   28   *    may be used to endorse or promote products derived from this software
  29   29   *    without specific prior written permission.
  30   30   *
  31   31   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  32   32   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33   33   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34   34   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  35   35   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36   36   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37   37   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38   38   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39   39   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40   40   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41   41   * SUCH DAMAGE.
  42   42   *  
  43   43   *
  44   44   * Copyright (c) 1990, 1991 Carnegie Mellon University
  45   45   * All Rights Reserved.
  46   46   *
  47   47   * Author: David Golub
  48   48   * 
  49   49   * Permission to use, copy, modify and distribute this software and its
  50   50   * documentation is hereby granted, provided that both the copyright
  51   51   * notice and this permission notice appear in all copies of the
  52   52   * software, derivative works or modified versions, and any portions
  53   53   * thereof, and that both notices appear in supporting documentation.
  54   54   * 
  55   55   * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  56   56   * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  57   57   * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  58   58   * 
  59   59   * Carnegie Mellon requests users of this software to return to
  60   60   * 
  61   61   *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  62   62   *  School of Computer Science
  63   63   *  Carnegie Mellon University
  64   64   *  Pittsburgh PA 15213-3890
  65   65   * 
  66   66   * any improvements or extensions that they make and grant Carnegie the
  67   67   * rights to redistribute these changes.
  68   68   */
  69   69  
  70   70  #include <sys/cdefs.h>
  71   71  
  72   72  /*
  73   73   *      Stand-alone file reading package.
  74   74   */
  75   75  
  
    | 
      ↓ open down ↓ | 
    62 lines elided | 
    
      ↑ open up ↑ | 
  
  76   76  #include <sys/param.h>
  77   77  #include <sys/disklabel.h>
  78   78  #include <sys/time.h>
  79   79  #include <ufs/ufs/dinode.h>
  80   80  #include <ufs/ufs/dir.h>
  81   81  #include <ufs/ffs/fs.h>
  82   82  #include "stand.h"
  83   83  #include "string.h"
  84   84  
  85   85  static int      ufs_open(const char *path, struct open_file *f);
  86      -static int      ufs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
       86 +static int      ufs_write(struct open_file *f, const void *buf, size_t size,
       87 +        size_t *resid);
  87   88  static int      ufs_close(struct open_file *f);
  88   89  static int      ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
  89   90  static off_t    ufs_seek(struct open_file *f, off_t offset, int where);
  90   91  static int      ufs_stat(struct open_file *f, struct stat *sb);
  91   92  static int      ufs_readdir(struct open_file *f, struct dirent *d);
  92   93  
  93   94  struct fs_ops ufs_fsops = {
  94   95          "ufs",
  95   96          ufs_open,
  96   97          ufs_close,
  97   98          ufs_read,
  98   99          ufs_write,
  99  100          ufs_seek,
 100  101          ufs_stat,
 101  102          ufs_readdir
 102  103  };
 103  104  
 104  105  /*
 105  106   * In-core open file.
 106  107   */
 107  108  struct file {
 108  109          off_t           f_seekp;        /* seek pointer */
 109  110          struct fs       *f_fs;          /* pointer to super-block */
 110  111          union dinode {
 111  112                  struct ufs1_dinode di1;
 112  113                  struct ufs2_dinode di2;
 113  114          }               f_di;           /* copy of on-disk inode */
 114  115          int             f_nindir[NIADDR];
 115  116                                          /* number of blocks mapped by
 116  117                                             indirect block at level i */
 117  118          char            *f_blk[NIADDR]; /* buffer for indirect block at
 118  119                                             level i */
 119  120          size_t          f_blksize[NIADDR];
 120  121                                          /* size of buffer */
 121  122          ufs2_daddr_t    f_blkno[NIADDR];/* disk address of block in buffer */
 122  123          ufs2_daddr_t    f_buf_blkno;    /* block number of data block */
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
 123  124          char            *f_buf;         /* buffer for data block */
 124  125          size_t          f_buf_size;     /* size of data block */
 125  126  };
 126  127  #define DIP(fp, field) \
 127  128          ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
 128  129          (fp)->f_di.di1.field : (fp)->f_di.di2.field)
 129  130  
 130  131  static int      read_inode(ino_t, struct open_file *);
 131  132  static int      block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
 132  133  static int      buf_read_file(struct open_file *, char **, size_t *);
 133      -static int      buf_write_file(struct open_file *, char *, size_t *);
      134 +static int      buf_write_file(struct open_file *, const char *, size_t *);
 134  135  static int      search_directory(char *, struct open_file *, ino_t *);
 135  136  
 136  137  /*
 137  138   * Read a new inode into a file structure.
 138  139   */
 139  140  static int
 140  141  read_inode(inumber, f)
 141  142          ino_t inumber;
 142  143          struct open_file *f;
 143  144  {
 144  145          struct file *fp = (struct file *)f->f_fsdata;
 145  146          struct fs *fs = fp->f_fs;
 146  147          char *buf;
 147  148          size_t rsize;
 148  149          int rc;
 149  150  
 150  151          if (fs == NULL)
 151  152              panic("fs == NULL");
 152  153  
 153  154          /*
 154  155           * Read inode and save it.
 155  156           */
 156  157          buf = malloc(fs->fs_bsize);
 157  158          twiddle(1);
 158  159          rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
 159  160                  fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
 160  161                  buf, &rsize);
 161  162          if (rc)
 162  163                  goto out;
 163  164          if (rsize != fs->fs_bsize) {
 164  165                  rc = EIO;
 165  166                  goto out;
 166  167          }
 167  168  
 168  169          if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
 169  170                  fp->f_di.di1 = ((struct ufs1_dinode *)buf)
 170  171                      [ino_to_fsbo(fs, inumber)];
 171  172          else
 172  173                  fp->f_di.di2 = ((struct ufs2_dinode *)buf)
 173  174                      [ino_to_fsbo(fs, inumber)];
 174  175  
 175  176          /*
 176  177           * Clear out the old buffers
 177  178           */
 178  179          {
 179  180                  int level;
 180  181  
 181  182                  for (level = 0; level < NIADDR; level++)
 182  183                          fp->f_blkno[level] = -1;
 183  184                  fp->f_buf_blkno = -1;
 184  185          }
 185  186          fp->f_seekp = 0;
 186  187  out:
 187  188          free(buf);
 188  189          return (rc);     
 189  190  }
 190  191  
 191  192  /*
 192  193   * Given an offset in a file, find the disk block number that
 193  194   * contains that block.
 194  195   */
 195  196  static int
 196  197  block_map(f, file_block, disk_block_p)
 197  198          struct open_file *f;
 198  199          ufs2_daddr_t file_block;
 199  200          ufs2_daddr_t *disk_block_p;     /* out */
 200  201  {
 201  202          struct file *fp = (struct file *)f->f_fsdata;
 202  203          struct fs *fs = fp->f_fs;
 203  204          int level;
 204  205          int idx;
 205  206          ufs2_daddr_t ind_block_num;
 206  207          int rc;
 207  208  
 208  209          /*
 209  210           * Index structure of an inode:
 210  211           *
 211  212           * di_db[0..NDADDR-1]   hold block numbers for blocks
 212  213           *                      0..NDADDR-1
 213  214           *
 214  215           * di_ib[0]             index block 0 is the single indirect block
 215  216           *                      holds block numbers for blocks
 216  217           *                      NDADDR .. NDADDR + NINDIR(fs)-1
 217  218           *
 218  219           * di_ib[1]             index block 1 is the double indirect block
 219  220           *                      holds block numbers for INDEX blocks for blocks
 220  221           *                      NDADDR + NINDIR(fs) ..
 221  222           *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
 222  223           *
 223  224           * di_ib[2]             index block 2 is the triple indirect block
 224  225           *                      holds block numbers for double-indirect
 225  226           *                      blocks for blocks
 226  227           *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
 227  228           *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2
 228  229           *                              + NINDIR(fs)**3 - 1
 229  230           */
 230  231  
 231  232          if (file_block < NDADDR) {
 232  233                  /* Direct block. */
 233  234                  *disk_block_p = DIP(fp, di_db[file_block]);
 234  235                  return (0);
 235  236          }
 236  237  
 237  238          file_block -= NDADDR;
 238  239  
 239  240          /*
 240  241           * nindir[0] = NINDIR
 241  242           * nindir[1] = NINDIR**2
 242  243           * nindir[2] = NINDIR**3
 243  244           *      etc
 244  245           */
 245  246          for (level = 0; level < NIADDR; level++) {
 246  247                  if (file_block < fp->f_nindir[level])
 247  248                          break;
 248  249                  file_block -= fp->f_nindir[level];
 249  250          }
 250  251          if (level == NIADDR) {
 251  252                  /* Block number too high */
 252  253                  return (EFBIG);
 253  254          }
 254  255  
 255  256          ind_block_num = DIP(fp, di_ib[level]);
 256  257  
 257  258          for (; level >= 0; level--) {
 258  259                  if (ind_block_num == 0) {
 259  260                          *disk_block_p = 0;      /* missing */
 260  261                          return (0);
 261  262                  }
 262  263  
 263  264                  if (fp->f_blkno[level] != ind_block_num) {
 264  265                          if (fp->f_blk[level] == (char *)0)
 265  266                                  fp->f_blk[level] =
 266  267                                          malloc(fs->fs_bsize);
 267  268                          twiddle(1);
 268  269                          rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
 269  270                                  fsbtodb(fp->f_fs, ind_block_num),
 270  271                                  fs->fs_bsize,
 271  272                                  fp->f_blk[level],
 272  273                                  &fp->f_blksize[level]);
 273  274                          if (rc)
 274  275                                  return (rc);
 275  276                          if (fp->f_blksize[level] != fs->fs_bsize)
 276  277                                  return (EIO);
 277  278                          fp->f_blkno[level] = ind_block_num;
 278  279                  }
 279  280  
 280  281                  if (level > 0) {
 281  282                          idx = file_block / fp->f_nindir[level - 1];
 282  283                          file_block %= fp->f_nindir[level - 1];
 283  284                  } else
 284  285                          idx = file_block;
 285  286  
 286  287                  if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
 287  288                          ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx];
 288  289                  else
 289  290                          ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx];
 290  291          }
 291  292  
 292  293          *disk_block_p = ind_block_num;
  
    | 
      ↓ open down ↓ | 
    149 lines elided | 
    
      ↑ open up ↑ | 
  
 293  294  
 294  295          return (0);
 295  296  }
 296  297  
 297  298  /*
 298  299   * Write a portion of a file from an internal buffer.
 299  300   */
 300  301  static int
 301  302  buf_write_file(f, buf_p, size_p)
 302  303          struct open_file *f;
 303      -        char *buf_p;
      304 +        const char *buf_p;
 304  305          size_t *size_p;         /* out */
 305  306  {
 306  307          struct file *fp = (struct file *)f->f_fsdata;
 307  308          struct fs *fs = fp->f_fs;
 308  309          long off;
 309  310          ufs_lbn_t file_block;
 310  311          ufs2_daddr_t disk_block;
 311  312          size_t block_size;
 312  313          int rc;
 313  314  
 314  315          /*
 315  316           * Calculate the starting block address and offset.
 316  317           */
 317  318          off = blkoff(fs, fp->f_seekp);
 318  319          file_block = lblkno(fs, fp->f_seekp);
 319  320          block_size = sblksize(fs, DIP(fp, di_size), file_block);
 320  321  
 321  322          rc = block_map(f, file_block, &disk_block);
 322  323          if (rc)
 323  324                  return (rc);
 324  325  
 325  326          if (disk_block == 0)
 326  327                  /* Because we can't allocate space on the drive */
 327  328                  return (EFBIG);
 328  329  
 329  330          /*
 330  331           * Truncate buffer at end of file, and at the end of
 331  332           * this block.
 332  333           */
 333  334          if (*size_p > DIP(fp, di_size) - fp->f_seekp)
 334  335                  *size_p = DIP(fp, di_size) - fp->f_seekp;
 335  336          if (*size_p > block_size - off) 
 336  337                  *size_p = block_size - off;
 337  338  
 338  339          /*
 339  340           * If we don't entirely occlude the block and it's not
 340  341           * in memory already, read it in first.
 341  342           */
 342  343          if (((off > 0) || (*size_p + off < block_size)) &&
 343  344              (file_block != fp->f_buf_blkno)) {
 344  345  
 345  346                  if (fp->f_buf == (char *)0)
 346  347                          fp->f_buf = malloc(fs->fs_bsize);
 347  348  
 348  349                  twiddle(8);
 349  350                  rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
 350  351                          fsbtodb(fs, disk_block),
 351  352                          block_size, fp->f_buf, &fp->f_buf_size);
 352  353                  if (rc)
 353  354                          return (rc);
 354  355  
 355  356                  fp->f_buf_blkno = file_block;
 356  357          }
 357  358  
 358  359          /*
 359  360           *      Copy the user data into the cached block.
 360  361           */
 361  362          bcopy(buf_p, fp->f_buf + off, *size_p);
 362  363  
 363  364          /*
 364  365           *      Write the block out to storage.
 365  366           */
 366  367  
 367  368          twiddle(4);
 368  369          rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
 369  370                  fsbtodb(fs, disk_block),
 370  371                  block_size, fp->f_buf, &fp->f_buf_size);
 371  372          return (rc);
 372  373  }
 373  374  
 374  375  /*
 375  376   * Read a portion of a file into an internal buffer.  Return
 376  377   * the location in the buffer and the amount in the buffer.
 377  378   */
 378  379  static int
 379  380  buf_read_file(f, buf_p, size_p)
 380  381          struct open_file *f;
 381  382          char **buf_p;           /* out */
 382  383          size_t *size_p;         /* out */
 383  384  {
 384  385          struct file *fp = (struct file *)f->f_fsdata;
 385  386          struct fs *fs = fp->f_fs;
 386  387          long off;
 387  388          ufs_lbn_t file_block;
 388  389          ufs2_daddr_t disk_block;
 389  390          size_t block_size;
 390  391          int rc;
 391  392  
 392  393          off = blkoff(fs, fp->f_seekp);
 393  394          file_block = lblkno(fs, fp->f_seekp);
 394  395          block_size = sblksize(fs, DIP(fp, di_size), file_block);
 395  396  
 396  397          if (file_block != fp->f_buf_blkno) {
 397  398                  if (fp->f_buf == (char *)0)
 398  399                          fp->f_buf = malloc(fs->fs_bsize);
 399  400  
 400  401                  rc = block_map(f, file_block, &disk_block);
 401  402                  if (rc)
 402  403                          return (rc);
 403  404  
 404  405                  if (disk_block == 0) {
 405  406                          bzero(fp->f_buf, block_size);
 406  407                          fp->f_buf_size = block_size;
 407  408                  } else {
 408  409                          twiddle(4);
 409  410                          rc = (f->f_dev->dv_strategy)(f->f_devdata,
 410  411                                  F_READ, fsbtodb(fs, disk_block),
 411  412                                  block_size, fp->f_buf, &fp->f_buf_size);
 412  413                          if (rc)
 413  414                                  return (rc);
 414  415                  }
 415  416  
 416  417                  fp->f_buf_blkno = file_block;
 417  418          }
 418  419  
 419  420          /*
 420  421           * Return address of byte in buffer corresponding to
 421  422           * offset, and size of remainder of buffer after that
 422  423           * byte.
 423  424           */
 424  425          *buf_p = fp->f_buf + off;
 425  426          *size_p = block_size - off;
 426  427  
 427  428          /*
 428  429           * But truncate buffer at end of file.
 429  430           */
 430  431          if (*size_p > DIP(fp, di_size) - fp->f_seekp)
 431  432                  *size_p = DIP(fp, di_size) - fp->f_seekp;
 432  433  
 433  434          return (0);
 434  435  }
 435  436  
 436  437  /*
 437  438   * Search a directory for a name and return its
 438  439   * i_number.
 439  440   */
 440  441  static int
 441  442  search_directory(name, f, inumber_p)
 442  443          char *name;
 443  444          struct open_file *f;
 444  445          ino_t *inumber_p;               /* out */
 445  446  {
 446  447          struct file *fp = (struct file *)f->f_fsdata;
 447  448          struct direct *dp;
 448  449          struct direct *edp;
 449  450          char *buf;
 450  451          size_t buf_size;
 451  452          int namlen, length;
 452  453          int rc;
 453  454  
 454  455          length = strlen(name);
 455  456  
 456  457          fp->f_seekp = 0;
 457  458          while (fp->f_seekp < DIP(fp, di_size)) {
 458  459                  rc = buf_read_file(f, &buf, &buf_size);
 459  460                  if (rc)
 460  461                          return (rc);
 461  462  
 462  463                  dp = (struct direct *)buf;
 463  464                  edp = (struct direct *)(buf + buf_size);
 464  465                  while (dp < edp) {
 465  466                          if (dp->d_ino == (ino_t)0)
 466  467                                  goto next;
 467  468                          namlen = dp->d_namlen;
 468  469                          if (namlen == length &&
 469  470                              !strcmp(name, dp->d_name)) {
 470  471                                  /* found entry */
 471  472                                  *inumber_p = dp->d_ino;
 472  473                                  return (0);
 473  474                          }
 474  475                  next:
 475  476                          dp = (struct direct *)((char *)dp + dp->d_reclen);
 476  477                  }
 477  478                  fp->f_seekp += buf_size;
 478  479          }
 479  480          return (ENOENT);
 480  481  }
 481  482  
 482  483  static int sblock_try[] = SBLOCKSEARCH;
 483  484  
 484  485  /*
 485  486   * Open a file.
 486  487   */
 487  488  static int
 488  489  ufs_open(upath, f)
 489  490          const char *upath;
 490  491          struct open_file *f;
 491  492  {
 492  493          char *cp, *ncp;
 493  494          int c;
 494  495          ino_t inumber, parent_inumber;
 495  496          struct file *fp;
 496  497          struct fs *fs;
 497  498          int i, rc;
 498  499          size_t buf_size;
 499  500          int nlinks = 0;
 500  501          char namebuf[MAXPATHLEN+1];
 501  502          char *buf = NULL;
 502  503          char *path = NULL;
 503  504  
 504  505          /* allocate file system specific data structure */
 505  506          fp = malloc(sizeof(struct file));
 506  507          bzero(fp, sizeof(struct file));
 507  508          f->f_fsdata = (void *)fp;
 508  509  
 509  510          /* allocate space and read super block */
 510  511          fs = malloc(SBLOCKSIZE);
 511  512          fp->f_fs = fs;
 512  513          twiddle(1);
 513  514          /*
 514  515           * Try reading the superblock in each of its possible locations.
 515  516           */
 516  517          for (i = 0; sblock_try[i] != -1; i++) {
 517  518                  rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
 518  519                      sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
 519  520                      (char *)fs, &buf_size);
 520  521                  if (rc)
 521  522                          goto out;
 522  523                  if ((fs->fs_magic == FS_UFS1_MAGIC ||
 523  524                       (fs->fs_magic == FS_UFS2_MAGIC &&
 524  525                        fs->fs_sblockloc == sblock_try[i])) &&
 525  526                      buf_size == SBLOCKSIZE &&
 526  527                      fs->fs_bsize <= MAXBSIZE &&
 527  528                      fs->fs_bsize >= sizeof(struct fs))
 528  529                          break;
 529  530          }
 530  531          if (sblock_try[i] == -1) {
 531  532                  rc = EINVAL;
 532  533                  goto out;
 533  534          }
 534  535          /*
 535  536           * Calculate indirect block levels.
 536  537           */
 537  538          {
 538  539                  ufs2_daddr_t mult;
 539  540                  int level;
 540  541  
 541  542                  mult = 1;
 542  543                  for (level = 0; level < NIADDR; level++) {
 543  544                          mult *= NINDIR(fs);
 544  545                          fp->f_nindir[level] = mult;
 545  546                  }
 546  547          }
 547  548  
 548  549          inumber = ROOTINO;
 549  550          if ((rc = read_inode(inumber, f)) != 0)
 550  551                  goto out;
 551  552  
 552  553          cp = path = strdup(upath);
 553  554          if (path == NULL) {
 554  555              rc = ENOMEM;
 555  556              goto out;
 556  557          }
 557  558          while (*cp) {
 558  559  
 559  560                  /*
 560  561                   * Remove extra separators
 561  562                   */
 562  563                  while (*cp == '/')
 563  564                          cp++;
 564  565                  if (*cp == '\0')
 565  566                          break;
 566  567  
 567  568                  /*
 568  569                   * Check that current node is a directory.
 569  570                   */
 570  571                  if ((DIP(fp, di_mode) & IFMT) != IFDIR) {
 571  572                          rc = ENOTDIR;
 572  573                          goto out;
 573  574                  }
 574  575  
 575  576                  /*
 576  577                   * Get next component of path name.
 577  578                   */
 578  579                  {
 579  580                          int len = 0;
 580  581  
 581  582                          ncp = cp;
 582  583                          while ((c = *cp) != '\0' && c != '/') {
 583  584                                  if (++len > UFS_MAXNAMLEN) {
 584  585                                          rc = ENOENT;
 585  586                                          goto out;
 586  587                                  }
 587  588                                  cp++;
 588  589                          }
 589  590                          *cp = '\0';
 590  591                  }
 591  592  
 592  593                  /*
 593  594                   * Look up component in current directory.
 594  595                   * Save directory inumber in case we find a
 595  596                   * symbolic link.
 596  597                   */
 597  598                  parent_inumber = inumber;
 598  599                  rc = search_directory(ncp, f, &inumber);
 599  600                  *cp = c;
 600  601                  if (rc)
 601  602                          goto out;
 602  603  
 603  604                  /*
 604  605                   * Open next component.
 605  606                   */
 606  607                  if ((rc = read_inode(inumber, f)) != 0)
 607  608                          goto out;
 608  609  
 609  610                  /*
 610  611                   * Check for symbolic link.
 611  612                   */
 612  613                  if ((DIP(fp, di_mode) & IFMT) == IFLNK) {
 613  614                          int link_len = DIP(fp, di_size);
 614  615                          int len;
 615  616  
 616  617                          len = strlen(cp);
 617  618  
 618  619                          if (link_len + len > MAXPATHLEN ||
 619  620                              ++nlinks > MAXSYMLINKS) {
 620  621                                  rc = ENOENT;
 621  622                                  goto out;
 622  623                          }
 623  624  
 624  625                          bcopy(cp, &namebuf[link_len], len + 1);
 625  626  
 626  627                          if (link_len < fs->fs_maxsymlinklen) {
 627  628                                  if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
 628  629                                          cp = (caddr_t)(fp->f_di.di1.di_db);
 629  630                                  else
 630  631                                          cp = (caddr_t)(fp->f_di.di2.di_db);
 631  632                                  bcopy(cp, namebuf, (unsigned) link_len);
 632  633                          } else {
 633  634                                  /*
 634  635                                   * Read file for symbolic link
 635  636                                   */
 636  637                                  size_t buf_size;
 637  638                                  ufs2_daddr_t disk_block;
 638  639                                  struct fs *fs = fp->f_fs;
 639  640  
 640  641                                  if (!buf)
 641  642                                          buf = malloc(fs->fs_bsize);
 642  643                                  rc = block_map(f, (ufs2_daddr_t)0, &disk_block);
 643  644                                  if (rc)
 644  645                                          goto out;
 645  646                                  
 646  647                                  twiddle(1);
 647  648                                  rc = (f->f_dev->dv_strategy)(f->f_devdata,
 648  649                                          F_READ, fsbtodb(fs, disk_block),
 649  650                                          fs->fs_bsize, buf, &buf_size);
 650  651                                  if (rc)
 651  652                                          goto out;
 652  653  
 653  654                                  bcopy((char *)buf, namebuf, (unsigned)link_len);
 654  655                          }
 655  656  
 656  657                          /*
 657  658                           * If relative pathname, restart at parent directory.
 658  659                           * If absolute pathname, restart at root.
 659  660                           */
 660  661                          cp = namebuf;
 661  662                          if (*cp != '/')
 662  663                                  inumber = parent_inumber;
 663  664                          else
 664  665                                  inumber = (ino_t)ROOTINO;
 665  666  
 666  667                          if ((rc = read_inode(inumber, f)) != 0)
 667  668                                  goto out;
 668  669                  }
 669  670          }
 670  671  
 671  672          /*
 672  673           * Found terminal component.
 673  674           */
 674  675          rc = 0;
 675  676          fp->f_seekp = 0;
 676  677  out:
 677  678          if (buf)
 678  679                  free(buf);
 679  680          if (path)
 680  681                  free(path);
 681  682          if (rc) {
 682  683                  if (fp->f_buf)
 683  684                          free(fp->f_buf);
 684  685                  free(fp->f_fs);
 685  686                  free(fp);
 686  687          }
 687  688          return (rc);
 688  689  }
 689  690  
 690  691  static int
 691  692  ufs_close(f)
 692  693          struct open_file *f;
 693  694  {
 694  695          struct file *fp = (struct file *)f->f_fsdata;
 695  696          int level;
 696  697  
 697  698          f->f_fsdata = (void *)0;
 698  699          if (fp == (struct file *)0)
 699  700                  return (0);
 700  701  
 701  702          for (level = 0; level < NIADDR; level++) {
 702  703                  if (fp->f_blk[level])
 703  704                          free(fp->f_blk[level]);
 704  705          }
 705  706          if (fp->f_buf)
 706  707                  free(fp->f_buf);
 707  708          free(fp->f_fs);
 708  709          free(fp);
 709  710          return (0);
 710  711  }
 711  712  
 712  713  /*
 713  714   * Copy a portion of a file into kernel memory.
 714  715   * Cross block boundaries when necessary.
 715  716   */
 716  717  static int
 717  718  ufs_read(f, start, size, resid)
 718  719          struct open_file *f;
 719  720          void *start;
 720  721          size_t size;
 721  722          size_t *resid;  /* out */
 722  723  {
 723  724          struct file *fp = (struct file *)f->f_fsdata;
 724  725          size_t csize;
 725  726          char *buf;
 726  727          size_t buf_size;
 727  728          int rc = 0;
 728  729          char *addr = start;
 729  730  
 730  731          while (size != 0) {
 731  732                  if (fp->f_seekp >= DIP(fp, di_size))
 732  733                          break;
 733  734  
 734  735                  rc = buf_read_file(f, &buf, &buf_size);
 735  736                  if (rc)
 736  737                          break;
 737  738  
 738  739                  csize = size;
 739  740                  if (csize > buf_size)
 740  741                          csize = buf_size;
 741  742  
 742  743                  bcopy(buf, addr, csize);
 743  744  
 744  745                  fp->f_seekp += csize;
 745  746                  addr += csize;
 746  747                  size -= csize;
 747  748          }
 748  749          if (resid)
 749  750                  *resid = size;
 750  751          return (rc);
  
    | 
      ↓ open down ↓ | 
    437 lines elided | 
    
      ↑ open up ↑ | 
  
 751  752  }
 752  753  
 753  754  /*
 754  755   * Write to a portion of an already allocated file.
 755  756   * Cross block boundaries when necessary. Can not
 756  757   * extend the file.
 757  758   */
 758  759  static int
 759  760  ufs_write(f, start, size, resid)
 760  761          struct open_file *f;
 761      -        void *start;
      762 +        const void *start;
 762  763          size_t size;
 763  764          size_t *resid;  /* out */
 764  765  {
 765  766          struct file *fp = (struct file *)f->f_fsdata;
 766  767          size_t csize;
 767  768          int rc = 0;
 768      -        char *addr = start;
      769 +        const char *addr = start;
 769  770  
 770  771          csize = size;
 771  772          while ((size != 0) && (csize != 0)) {
 772  773                  if (fp->f_seekp >= DIP(fp, di_size))
 773  774                          break;
 774  775  
 775  776                  if (csize >= 512) csize = 512; /* XXX */
 776  777  
 777  778                  rc = buf_write_file(f, addr, &csize);
 778  779                  if (rc)
 779  780                          break;
 780  781  
 781  782                  fp->f_seekp += csize;
 782  783                  addr += csize;
 783  784                  size -= csize;
 784  785          }
 785  786          if (resid)
 786  787                  *resid = size;
 787  788          return (rc);
 788  789  }
 789  790  
 790  791  static off_t
 791  792  ufs_seek(f, offset, where)
 792  793          struct open_file *f;
 793  794          off_t offset;
 794  795          int where;
 795  796  {
 796  797          struct file *fp = (struct file *)f->f_fsdata;
 797  798  
 798  799          switch (where) {
 799  800          case SEEK_SET:
 800  801                  fp->f_seekp = offset;
 801  802                  break;
 802  803          case SEEK_CUR:
 803  804                  fp->f_seekp += offset;
 804  805                  break;
 805  806          case SEEK_END:
 806  807                  fp->f_seekp = DIP(fp, di_size) - offset;
 807  808                  break;
 808  809          default:
 809  810                  errno = EINVAL;
 810  811                  return (-1);
 811  812          }
 812  813          return (fp->f_seekp);
 813  814  }
 814  815  
 815  816  static int
 816  817  ufs_stat(f, sb)
 817  818          struct open_file *f;
 818  819          struct stat *sb;
 819  820  {
 820  821          struct file *fp = (struct file *)f->f_fsdata;
 821  822  
 822  823          /* only important stuff */
 823  824          sb->st_mode = DIP(fp, di_mode);
 824  825          sb->st_uid = DIP(fp, di_uid);
 825  826          sb->st_gid = DIP(fp, di_gid);
 826  827          sb->st_size = DIP(fp, di_size);
 827  828          return (0);
 828  829  }
 829  830  
 830  831  static int
 831  832  ufs_readdir(struct open_file *f, struct dirent *d)
 832  833  {
 833  834          struct file *fp = (struct file *)f->f_fsdata;
 834  835          struct direct *dp;
 835  836          char *buf;
 836  837          size_t buf_size;
 837  838          int error;
 838  839  
 839  840          /*
 840  841           * assume that a directory entry will not be split across blocks
 841  842           */
 842  843  again:
 843  844          if (fp->f_seekp >= DIP(fp, di_size))
 844  845                  return (ENOENT);
 845  846          error = buf_read_file(f, &buf, &buf_size);
 846  847          if (error)
 847  848                  return (error);
 848  849          dp = (struct direct *)buf;
 849  850          fp->f_seekp += dp->d_reclen;
 850  851          if (dp->d_ino == (ino_t)0)
 851  852                  goto again;
 852  853  
 853  854          d->d_type = 0;          /* illumos ufs does not have type in direct */
 854  855          strcpy(d->d_name, dp->d_name);
 855  856          return (0);
 856  857  }
  
    | 
      ↓ open down ↓ | 
    78 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX