/* * (C) Copyright 2011 * Heiko Schocher, DENX Software Engineering, hs@denx.de. * * Based on: * (C) Copyright 2009 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. * * (C) Copyright 2008 * Marvell Semiconductor * Written-by: Prafulla Wadaskar * * SPDX-License-Identifier: GPL-2.0+ */ #include "imagetool.h" #include #include "ublimage.h" /* * Supported commands for configuration file */ static table_entry_t ublimage_cmds[] = { {CMD_BOOT_MODE, "MODE", "UBL special modes", }, {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", }, {CMD_PAGE, "PAGES", "number of pages (size of bootloader)", }, {CMD_ST_BLOCK, "START_BLOCK", "block number where bootloader is present", }, {CMD_ST_PAGE, "START_PAGE", "page number where bootloader is present", }, {CMD_LD_ADDR, "LD_ADDR", "load addr", }, {-1, "", "", }, }; /* * Supported Boot options for configuration file * this is needed to set the correct flash offset */ static table_entry_t ublimage_bootops[] = { {UBL_MAGIC_SAFE, "safe", "Safe boot mode", }, {-1, "", "Invalid", }, }; static struct ubl_header ublimage_header; static uint32_t get_cfg_value(char *token, char *name, int linenr) { char *endptr; uint32_t value; errno = 0; value = strtoul(token, &endptr, 16); if (errno || (token == endptr)) { fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", name, linenr, token); exit(EXIT_FAILURE); } return value; } static void print_hdr(struct ubl_header *ubl_hdr) { printf("Image Type : Davinci UBL Boot Image\n"); printf("UBL magic : %08x\n", ubl_hdr->magic); printf("Entry Point: %08x\n", ubl_hdr->entry); printf("nr of pages: %08x\n", ubl_hdr->pages); printf("start block: %08x\n", ubl_hdr->block); printf("start page : %08x\n", ubl_hdr->page); } static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token, char *name, int lineno, int fld, int dcd_len) { static int cmd_ver_first = ~0; switch (cmd) { case CMD_BOOT_MODE: ublhdr->magic = get_table_entry_id(ublimage_bootops, "ublimage special boot mode", token); if (ublhdr->magic == -1) { fprintf(stderr, "Error: %s[%d] -Invalid boot mode" "(%s)\n", name, lineno, token); exit(EXIT_FAILURE); } ublhdr->magic += UBL_MAGIC_BASE; if (unlikely(cmd_ver_first != 1)) cmd_ver_first = 0; break; case CMD_ENTRY: ublhdr->entry = get_cfg_value(token, name, lineno); break; case CMD_PAGE: ublhdr->pages = get_cfg_value(token, name, lineno); break; case CMD_ST_BLOCK: ublhdr->block = get_cfg_value(token, name, lineno); break; case CMD_ST_PAGE: ublhdr->page = get_cfg_value(token, name, lineno); break; case CMD_LD_ADDR: ublhdr->pll_m = get_cfg_value(token, name, lineno); break; } } static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd, char *token, char *name, int lineno, int fld, int *dcd_len) { switch (fld) { case CFG_COMMAND: *cmd = get_table_entry_id(ublimage_cmds, "ublimage commands", token); if (*cmd < 0) { fprintf(stderr, "Error: %s[%d] - Invalid command" "(%s)\n", name, lineno, token); exit(EXIT_FAILURE); } break; case CFG_REG_VALUE: parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len); break; default: break; } } static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name) { FILE *fd = NULL; char *line = NULL; char *token, *saveptr1, *saveptr2; int lineno = 0; int i; char *ptr = (char *)ublhdr; int fld; size_t len; int dcd_len = 0; int32_t cmd; int ublhdrlen = sizeof(struct ubl_header); fd = fopen(name, "r"); if (fd == 0) { fprintf(stderr, "Error: %s - Can't open DCD file\n", name); exit(EXIT_FAILURE); } /* Fill header with 0xff */ for (i = 0; i < ublhdrlen; i++) { *ptr = 0xff; ptr++; } /* * Very simple parsing, line starting with # are comments * and are dropped */ while ((getline(&line, &len, fd)) > 0) { lineno++; token = strtok_r(line, "\r\n", &saveptr1); if (token == NULL) continue; /* Check inside the single line */ for (fld = CFG_COMMAND, cmd = CMD_INVALID, line = token; ; line = NULL, fld++) { token = strtok_r(line, " \t", &saveptr2); if (token == NULL) break; /* Drop all text starting with '#' as comments */ if (token[0] == '#') break; parse_cfg_fld(ublhdr, &cmd, token, name, lineno, fld, &dcd_len); } } fclose(fd); return dcd_len; } static int ublimage_check_image_types(uint8_t type) { if (type == IH_TYPE_UBLIMAGE) return EXIT_SUCCESS; else return EXIT_FAILURE; } static int ublimage_verify_header(unsigned char *ptr, int image_size, struct image_tool_params *params) { struct ubl_header *ubl_hdr = (struct ubl_header *)ptr; if ((ubl_hdr->magic & 0xFFFFFF00) != UBL_MAGIC_BASE) return -1; return 0; } static void ublimage_print_header(const void *ptr) { struct ubl_header *ubl_hdr = (struct ubl_header *) ptr; print_hdr(ubl_hdr); } static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd, struct image_tool_params *params) { struct ubl_header *ublhdr = (struct ubl_header *)ptr; /* Parse configuration file */ parse_cfg_file(ublhdr, params->imagename); } int ublimage_check_params(struct image_tool_params *params) { if (!params) return CFG_INVALID; if (!strlen(params->imagename)) { fprintf(stderr, "Error: %s - Configuration file not" "specified, it is needed for ublimage generation\n", params->cmdname); return CFG_INVALID; } /* * Check parameters: * XIP is not allowed and verify that incompatible * parameters are not sent at the same time * For example, if list is required a data image must not be provided */ return (params->dflag && (params->fflag || params->lflag)) || (params->fflag && (params->dflag || params->lflag)) || (params->lflag && (params->dflag || params->fflag)) || (params->xflag) || !(strlen(params->imagename)); } /* * ublimage parameters */ U_BOOT_IMAGE_TYPE( ublimage, "Davinci UBL boot support", sizeof(struct ubl_header), (void *)&ublimage_header, ublimage_check_params, ublimage_verify_header, ublimage_print_header, ublimage_set_header, NULL, ublimage_check_image_types, NULL, NULL ); >75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
require 'test/unit'
require 'stringio'
require_relative '../ruby/ut_eof'

class TestStringIO < Test::Unit::TestCase
  include TestEOF
  def open_file(content)
    f = StringIO.new(content)
    yield f
  end
  alias open_file_rw open_file

  include TestEOF::Seek

  def test_truncate
    io = StringIO.new("")
    io.puts "abc"
    io.truncate(0)
    io.puts "def"
    assert_equal("\0\0\0\0def\n", io.string, "[ruby-dev:24190]")
    assert_raise(Errno::EINVAL) { io.truncate(-1) }
    io.truncate(10)
    assert_equal("\0\0\0\0def\n\0\0", io.string)
  end

  def test_seek_beyond_eof
    io = StringIO.new
    n = 100
    io.seek(n)
    io.print "last"
    assert_equal("\0" * n + "last", io.string, "[ruby-dev:24194]")
  end

  def test_overwrite
    stringio = StringIO.new
    responses = ['', 'just another ruby', 'hacker']
    responses.each do |resp|
      stringio.puts(resp)
      stringio.rewind
    end
    assert_equal("hacker\nother ruby\n", stringio.string, "[ruby-core:3836]")
  end

  def test_gets
    assert_equal(nil, StringIO.new("").gets)
    assert_equal("\n", StringIO.new("\n").gets)
    assert_equal("a\n", StringIO.new("a\n").gets)
    assert_equal("a\n", StringIO.new("a\nb\n").gets)
    assert_equal("a", StringIO.new("a").gets)
    assert_equal("a\n", StringIO.new("a\nb").gets)
    assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets)
    assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil))
    assert_equal("abc\n\n", StringIO.new("abc\n\ndef\n").gets(""))
  end

  def test_readlines
    assert_equal([], StringIO.new("").readlines)
    assert_equal(["\n"], StringIO.new("\n").readlines)
    assert_equal(["a\n"], StringIO.new("a\n").readlines)
    assert_equal(["a\n", "b\n"], StringIO.new("a\nb\n").readlines)
    assert_equal(["a"], StringIO.new("a").readlines)
    assert_equal(["a\n", "b"], StringIO.new("a\nb").readlines)
    assert_equal(["abc\n", "\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines)
    assert_equal(["abc\n\ndef\n"], StringIO.new("abc\n\ndef\n").readlines(nil), "[ruby-dev:34591]")
    assert_equal(["abc\n\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines(""))
  end

  def test_write
    s = ""
    f = StringIO.new(s, "w")
    f.print("foo")
    f.close
    assert_equal("foo", s)

    f = StringIO.new(s, File::WRONLY)
    f.print("bar")
    f.close
    assert_equal("bar", s)

    f = StringIO.new(s, "a")
    o = Object.new
    def o.to_s; "baz"; end
    f.print(o)
    f.close
    assert_equal("barbaz", s)
  ensure
    f.close unless f.closed?
  end

  def test_mode_error
    f = StringIO.new("", "r")
    assert_raise(IOError) { f.write("foo") }

    f = StringIO.new("", "w")
    assert_raise(IOError) { f.read }

    assert_raise(Errno::EACCES) { StringIO.new("".freeze, "w") }
    s = ""
    f = StringIO.new(s, "w")
    s.freeze
    assert_raise(IOError) { f.write("foo") }

    assert_raise(IOError) { StringIO.allocate.read }
  ensure
    f.close unless f.closed?
  end

  def test_open
    s = ""
    StringIO.open("foo") {|f| s = f.read }
    assert_equal("foo", s)
  end

  def test_isatty
    assert_equal(false, StringIO.new("").isatty)
  end

  def test_fsync
    assert_equal(0, StringIO.new("").fsync)
  end

  def test_sync
    assert_equal(true, StringIO.new("").sync)
    assert_equal(false, StringIO.new("").sync = false)
  end

  def test_set_fcntl
    assert_raise(NotImplementedError) { StringIO.new("").fcntl }
  end

  def test_close
    f = StringIO.new("")
    f.close
    assert_raise(IOError) { f.close }

    f = StringIO.new("")
    f.close_read
    f.close_write
    assert_raise(IOError) { f.close }
  ensure
    f.close unless f.closed?
  end

  def test_close_read
    f = StringIO.new("")
    f.close_read
    assert_raise(IOError) { f.read }
    assert_raise(IOError) { f.close_read }
    f.close

    f = StringIO.new("", "w")
    assert_raise(IOError) { f.close_read }
    f.close
  ensure
    f.close unless f.closed?
  end

  def test_close_write
    f = StringIO.new("")
    f.close_write
    assert_raise(IOError) { f.write("foo") }
    assert_raise(IOError) { f.close_write }
    f.close

    f = StringIO.new("", "r")
    assert_raise(IOError) { f.close_write }
    f.close
  ensure
    f.close unless f.closed?
  end

  def test_closed
    f = StringIO.new("")
    assert_equal(false, f.closed?)
    f.close
    assert_equal(true, f.closed?)
  ensure
    f.close unless f.closed?
  end

  def test_closed_read
    f = StringIO.new("")
    assert_equal(false, f.closed_read?)
    f.close_write
    assert_equal(false, f.closed_read?)
    f.close_read
    assert_equal(true, f.closed_read?)
  ensure
    f.close unless f.closed?
  end

  def test_closed_write
    f = StringIO.new("")
    assert_equal(false, f.closed_write?)
    f.close_read
    assert_equal(false, f.closed_write?)
    f.close_write
    assert_equal(true, f.closed_write?)
  ensure
    f.close unless f.closed?
  end

  def test_dup
    f1 = StringIO.new("1234")
    assert_equal("1", f1.getc)
    f2 = f1.dup
    assert_equal("2", f2.getc)
    assert_equal("3", f1.getc)
    assert_equal("4", f2.getc)
    assert_equal(nil, f1.getc)
    assert_equal(true, f2.eof?)
    f1.close
    assert_equal(true, f2.closed?)
  ensure
    f1.close unless f1.closed?
    f2.close unless f2.closed?
  end

  def test_lineno
    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal([0, "foo\n"], [f.lineno, f.gets])
    assert_equal([1, "bar\n"], [f.lineno, f.gets])
    f.lineno = 1000
    assert_equal([1000, "baz\n"], [f.lineno, f.gets])
    assert_equal([1001, nil], [f.lineno, f.gets])
  ensure
    f.close unless f.closed?
  end

  def test_pos
    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal([0, "foo\n"], [f.pos, f.gets])
    assert_equal([4, "bar\n"], [f.pos, f.gets])
    assert_raise(Errno::EINVAL) { f.pos = -1 }
    f.pos = 1
    assert_equal([1, "oo\n"], [f.pos, f.gets])
    assert_equal([4, "bar\n"], [f.pos, f.gets])
    assert_equal([8, "baz\n"], [f.pos, f.gets])
    assert_equal([12, nil], [f.pos, f.gets])
  ensure
    f.close unless f.closed?
  end

  def test_reopen
    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal("foo\n", f.gets)
    f.reopen("qux\nquux\nquuux\n")
    assert_equal("qux\n", f.gets)

    f2 = StringIO.new("")
    f2.reopen(f)
    assert_equal("quux\n", f2.gets)
  ensure
    f.close unless f.closed?
  end

  def test_seek
    f = StringIO.new("1234")
    assert_raise(Errno::EINVAL) { f.seek(-1) }
    f.seek(-1, 2)
    assert_equal("4", f.getc)
    assert_raise(Errno::EINVAL) { f.seek(1, 3) }
    f.close
    assert_raise(IOError) { f.seek(0) }
  ensure
    f.close unless f.closed?
  end

  def test_each_byte
    f = StringIO.new("1234")
    a = []
    f.each_byte {|c| a << c }
    assert_equal(%w(1 2 3 4).map {|c| c.ord }, a)
  ensure
    f.close unless f.closed?
  end

  def test_getbyte
    f = StringIO.new("1234")
    assert_equal("1".ord, f.getbyte)
    assert_equal("2".ord, f.getbyte)
    assert_equal("3".ord, f.getbyte)
    assert_equal("4".ord, f.getbyte)
    assert_equal(nil, f.getbyte)
  ensure
    f.close unless f.closed?
  end

  def test_ungetbyte
    s = "foo\nbar\n"
    t = StringIO.new(s, "r")
    t.ungetbyte(0x41)
    assert_equal(0x41, t.getbyte)
    t.ungetbyte("qux")
    assert_equal("quxfoo\n", t.gets)
    t.set_encoding("utf-8")
    t.ungetbyte(0x89)
    t.ungetbyte(0x8e)
    t.ungetbyte("\xe7")
    t.ungetbyte("\xe7\xb4\x85")
    assert_equal("\u7d05\u7389bar\n", t.gets)
  end

  def test_ungetc
    s = "1234"
    f = StringIO.new(s, "r")
    assert_nothing_raised { f.ungetc("x") }
    assert_equal("x", f.getc) # bug?
    assert_equal("1", f.getc)

    s = "1234"
    f = StringIO.new(s, "r")
    assert_equal("1", f.getc)
    f.ungetc("y".ord)
    assert_equal("y", f.getc)
    assert_equal("2", f.getc)
  ensure
    f.close unless f.closed?
  end

  def test_readchar
    f = StringIO.new("1234")
    a = ""
    assert_raise(EOFError) { loop { a << f.readchar } }
    assert_equal("1234", a)
  end

  def test_readbyte
    f = StringIO.new("1234")
    a = []
    assert_raise(EOFError) { loop { a << f.readbyte } }
    assert_equal("1234".unpack("C*"), a)
  end

  def test_each_char
    f = StringIO.new("1234")
    assert_equal(%w(1 2 3 4), f.each_char.to_a)
  end

  def test_each_codepoint
    f = StringIO.new("1234")
    assert_equal([49, 50, 51, 52], f.each_codepoint.to_a)
  end

  def test_gets2
    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal("fo", f.gets(2))

    o = Object.new
    def o.to_str; "z"; end
    assert_equal("o\nbar\nbaz", f.gets(o))

    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal("foo\nbar\nbaz", f.gets("az"))
    f = StringIO.new("a" * 10000 + "zz!")
    assert_equal("a" * 10000 + "zz", f.gets("zz"))
    f = StringIO.new("a" * 10000 + "zz!")
    assert_equal("a" * 10000 + "zz!", f.gets("zzz"))
  end

  def test_each
    f = StringIO.new("foo\nbar\nbaz\n")
    assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)
  end

  def test_putc
    s = ""
    f = StringIO.new(s, "w")
    f.putc("1")
    f.putc("2")
    f.putc("3")
    f.close
    assert_equal("123", s)

    s = "foo"
    f = StringIO.new(s, "a")
    f.putc("1")
    f.putc("2")
    f.putc("3")
    f.close
    assert_equal("foo123", s)
  end

  def test_read
    f = StringIO.new("1234")
    assert_raise(ArgumentError) { f.read(-1) }
    assert_raise(ArgumentError) { f.read(1, 2, 3) }
  end

  def test_size
    f = StringIO.new("1234")
    assert_equal(4, f.size)
  end

  # This test is should in ruby/test_method.rb
  # However this test depends on stringio library,
  # we write it here.
  class C < StringIO
    alias old_init initialize
    attr_reader :foo
    def initialize
      @foo = :ok
      old_init
    end
  end

  def test_method
    assert_equal(:ok, C.new.foo, 'Bug #632 [ruby-core:19282]')
  end

  def test_ungetc_pos
    b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
    s = StringIO.new( b )
    expected_pos = 0
    while n = s.getc
      assert_equal( expected_pos + 1, s.pos )

      s.ungetc( n )
      assert_equal( expected_pos, s.pos )
      assert_equal( n, s.getc )

      expected_pos += 1
    end
  end
end