/* * U-boot - bootldr.c * * Copyright (c) 2005-2008 Analog Devices Inc. * * See file CREDITS for list of people who contributed to this * project. * * Licensed under the GPL-2 or later. */ #include #include #include #include #include /* Simple sanity check on the specified address to make sure it contains * an LDR image of some sort. */ static bool ldr_valid_signature(uint8_t *data) { #if defined(__ADSPBF561__) /* BF56x has a 4 byte global header */ if (data[3] == (GFLAG_56X_SIGN_MAGIC << (GFLAG_56X_SIGN_SHIFT - 24))) return true; #elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) || \ defined(__ADSPBF538__) || defined(__ADSPBF539__) /* all the BF53x should start at this address mask */ uint32_t addr; memmove(&addr, data, sizeof(addr)); if ((addr & 0xFF0FFF0F) == 0xFF000000) return true; #else /* everything newer has a magic byte */ uint32_t count; memmove(&count, data + 8, sizeof(count)); if (data[3] == 0xAD && count == 0) return true; #endif return false; } /* If the Blackfin is new enough, the Blackfin on-chip ROM supports loading * LDRs from random memory addresses. So whenever possible, use that. In * the older cases (BF53x/BF561), parse the LDR format ourselves. */ static void ldr_load(uint8_t *base_addr) { #if defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ /*defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) ||*/\ defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) uint32_t addr; uint32_t count; uint16_t flags; /* the bf56x has a 4 byte global header ... but it is useless to * us when booting an LDR from a memory address, so skip it */ # ifdef __ADSPBF561__ base_addr += 4; # endif memmove(&flags, base_addr + 8, sizeof(flags)); bfin_write_EVT1(flags & BFLAG_53X_RESVECT ? 0xFFA00000 : 0xFFA08000); do { /* block header may not be aligned */ memmove(&addr, base_addr, sizeof(addr)); memmove(&count, base_addr+4, sizeof(count)); memmove(&flags, base_addr+8, sizeof(flags)); base_addr += sizeof(addr) + sizeof(count) + sizeof(flags); printf("loading to 0x%08x (%#x bytes) flags: 0x%04x\n", addr, count, flags); if (!(flags & BFLAG_53X_IGNORE)) { if (flags & BFLAG_53X_ZEROFILL) memset((void *)addr, 0x00, count); else memcpy((void *)addr, base_addr, count); if (flags & BFLAG_53X_INIT) { void (*init)(void) = (void *)addr; init(); } } if (!(flags & BFLAG_53X_ZEROFILL)) base_addr += count; } while (!(flags & BFLAG_53X_FINAL)); #endif } /* For BF537, we use the _BOOTROM_BOOT_DXE_FLASH funky ROM function. * For all other BF53x/BF56x, we just call the entry point. * For everything else (newer), we use _BOOTROM_MEMBOOT ROM function. */ static void ldr_exec(void *addr) { #if defined(__ADSPBF534__) || defined(__ADSPBF536__) || defined(__ADSPBF537__) /* restore EVT1 to reset value as this is what the bootrom uses as * the default entry point when booting the final block of LDRs */ bfin_write_EVT1(L1_INST_SRAM); __asm__("call (%0);" : : "a"(_BOOTROM_MEMBOOT), "q7"(addr) : "RETS", "memory"); #elif defined(__ADSPBF531__) || defined(__ADSPBF532__) || defined(__ADSPBF533__) || \ defined(__ADSPBF538__) || defined(__ADSPBF539__) || defined(__ADSPBF561__) void (*ldr_entry)(void) = (void *)bfin_read_EVT1(); ldr_entry(); #else int32_t (*BOOTROM_MEM)(void *, int32_t, int32_t, void *) = (void *)_BOOTROM_MEMBOOT; BOOTROM_MEM(addr, 0, 0, NULL); #endif } /* * the bootldr command loads an address, checks to see if there * is a Boot stream that the on-chip BOOTROM can understand, * and loads it via the BOOTROM Callback. It is possible * to also add booting from SPI, or TWI, but this function does * not currently support that. */ int do_bootldr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { void *addr; /* Get the address */ if (argc < 2) addr = (void *)load_addr; else addr = (void *)simple_strtoul(argv[1], NULL, 16); /* Check if it is a LDR file */ if (ldr_valid_signature(addr)) { printf("## Booting ldr image at 0x%p ...\n", addr); ldr_load(addr); icache_disable(); dcache_disable(); ldr_exec(addr); } else printf("## No ldr image at address 0x%p\n", addr); return 0; } U_BOOT_CMD( bootldr, 2, 0, do_bootldr, "boot ldr image from memory", "[addr]\n" "" ); '#n23'>23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 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 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
require 'test/unit'

require 'tmpdir'
require 'tempfile'
require_relative 'envutil'

class TestRubyOptions < Test::Unit::TestCase
  def ruby(*r, &b)
    EnvUtil.rubyexec(*r, &b)
  end

  def test_source_file
    ruby('') do |w, r, e|
      w.close
      assert_equal('', e.read)
      assert_equal('', r.read)
    end
  end

  def test_usage
    ruby('-h') do |w, r, e|
      w.close
      assert(r.readlines.size <= 24)
    end

    ruby('--help') do |w, r, e|
      w.close
      assert(r.readlines.size <= 24)
    end
  end

  def test_option_variables
    ruby('-e', 'p [$-p, $-l, $-a]') do |w, r, e|
      assert_equal('[false, false, false]', r.read.chomp)
    end

    ruby('-p', '-l', '-a', '-e', 'p [$-p, $-l, $-a]') do |w, r, e|
      w.puts 'foo'
      w.puts 'bar'
      w.puts 'baz'
      w.close_write
      r = r.readlines.map {|l| l.chomp }
      assert_equal(
        [ '[true, true, true]', 'foo',
          '[true, true, true]', 'bar',
          '[true, true, true]', 'baz' ], r)
    end
  end

  def test_warning
    ruby('-W0', '-e', 'p $-W') do |w, r, e|
      assert_equal('0', r.read.chomp)
    end
    ruby('-W1', '-e', 'p $-W') do |w, r, e|
      assert_equal('1', r.read.chomp)
    end
    ruby('-Wx', '-e', 'p $-W') do |w, r, e|
      assert_equal('1', r.read.chomp)
    end
    ruby('-W', '-e', 'p $-W') do |w, r, e|
      assert_equal('2', r.read.chomp)
    end
  end

  def test_safe_level
    ruby('-T', '-e', '') do |w, r, e|
      assert_match(/no -e allowed in tainted mode \(SecurityError\)/, e.read)
    end

    ruby('-T4', '-S', 'foo.rb') do |w, r, e|
      assert_match(/no -S allowed in tainted mode \(SecurityError\)/, e.read)
    end
  end

  def test_debug
    ruby('-de', 'p $DEBUG') do |w, r, e|
      assert_equal('true', r.read.chomp)
    end

    ruby('--debug', '-e', 'p $DEBUG') do |w, r, e|
      assert_equal('true', r.read.chomp)
    end
  end

  def test_verbose
    ruby('-vve', '') do |w, r, e|
      assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, r.read)
    end

    ruby('--verbose', '-e', 'p $VERBOSE') do |w, r, e|
      assert_equal('true', r.read.chomp)
    end

    ruby('--verbose') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end
  end

  def test_copyright
    ruby('--copyright') do |w, r, e|
      assert_match(/^ruby - Copyright \(C\) 1993-\d+ Yukihiro Matsumoto$/, r.read)
    end

    ruby('--verbose', '-e', 'p $VERBOSE') do |w, r, e|
      assert_equal('true', r.read.chomp)
    end
  end

  def test_enable
    ruby('--enable', 'all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--enable-all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--enable=all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--enable', 'foobarbazqux', '-e', '') do |w, r, e|
      assert_match(/unknown argument for --enable: `foobarbazqux'/, e.read)
    end

    ruby('--enable') do |w, r, e|
      assert_match(/missing argument for --enable/, e.read)
    end
  end

  def test_disable
    ruby('--disable', 'all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--disable-all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--disable=all', '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby('--disable', 'foobarbazqux', '-e', '') do |w, r, e|
      assert_match(/unknown argument for --disable: `foobarbazqux'/, e.read)
    end

    ruby('--disable') do |w, r, e|
      assert_match(/missing argument for --disable/, e.read)
    end
  end

  def test_kanji
    ruby('-KU') do |w, r, e|
      w.puts "p '\u3042'"
      w.close
      assert_equal("\"\u3042\"", r.read.chomp.force_encoding(Encoding.find('utf-8')))
    end

    ruby('-KE', '-e', '') do |w, r, e|
      assert_equal("", r.read)
      assert_equal("", e.read)
    end

    ruby('-KS', '-e', '') do |w, r, e|
      assert_equal("", r.read)
      assert_equal("", e.read)
    end

    ruby('-KN', '-e', '') do |w, r, e|
      assert_equal("", r.read)
      assert_equal("", e.read)
    end
  end

  def test_version
    ruby('--version') do |w, r, e|
      assert_match(/^ruby #{RUBY_VERSION} .*? \[#{RUBY_PLATFORM}\]$/, r.read)
    end
  end

  def test_eval
    ruby('-e') do |w, r, e|
      assert_match(/no code specified for -e \(RuntimeError\)/, e.read)
    end
  end

  def test_require
    ruby('-r', 'pp', '-e', 'pp 1') do |w, r, e|
      assert_equal('1', r.read.chomp)
    end
    ruby('-rpp', '-e', 'pp 1') do |w, r, e|
      w.close
      assert_equal('1', r.read.chomp)
    end
  end

  def test_include
    d = Dir.tmpdir
    ruby('-I' + d, '-e', '') do |w, r, e|
      assert_equal('', e.read.chomp)
      assert_equal('', r.read.chomp)
    end

    d = Dir.tmpdir
    ruby('-I', d, '-e', '') do |w, r, e|
      assert_equal('', e.read.chomp)
      assert_equal('', r.read.chomp)
    end
  end

  def test_separator
    ruby('-000', '-e', 'print gets') do |w, r, e|
      w.write "foo\nbar\0baz"
      w.close
      assert_equal('', e.read)
      assert_equal("foo\nbar\0baz", r.read)
    end

    ruby('-0141', '-e', 'print gets') do |w, r, e|
      w.write "foo\nbar\0baz"
      w.close
      assert_equal('', e.read)
      assert_equal("foo\nba", r.read)
    end

    ruby('-0e', 'print gets') do |w, r, e|
      w.write "foo\nbar\0baz"
      w.close
      assert_equal('', e.read)
      assert_equal("foo\nbar\0", r.read)
    end
  end

  def test_autosplit
    ruby('-an', '-F:', '-e', 'p $F') do |w, r, e|
      w.puts "foo:bar:baz"
      w.puts "qux:quux:quuux"
      w.close
      r = r.readlines.map {|l| l.chomp }
      assert_equal(['["foo", "bar", "baz\n"]', '["qux", "quux", "quuux\n"]'], r)
    end
  end

  def test_chdir
    ruby('-C') do |w, r, e|
      assert_match(/Can't chdir/, e.read)
    end

    ruby('-C', 'test_ruby_test_rubyoptions_foobarbazqux') do |w, r, e|
      assert_match(/Can't chdir/, e.read)
    end

    d = Dir.tmpdir
    ruby('-C', d, '-e', 'puts Dir.pwd') do |w, r, e|
      assert_equal('', e.read)
      assert(File.identical?(r.read.chomp, d))
    end
  end

  def test_yydebug
    ruby('-ye', '') do |w, r, e|
      assert_equal("", r.read)
      assert_nothing_raised { e.read }
    end

    ruby('--yydebug', '-e', '') do |w, r, e|
      assert_equal("", r.read)
      assert_nothing_raised { e.read }
    end
  end

  def test_encoding
    ruby('-Eutf-8') do |w, r, e|
      w.puts "p '\u3042'"
      w.close
      assert_match(/invalid multibyte char/, e.read)
    end

    ruby('--encoding') do |w, r, e|
      assert_match(/missing argument for --encoding/, e.read)
    end

    ruby('--encoding', 'test_ruby_test_rubyoptions_foobarbazqux') do |w, r, e|
      assert_match(/unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/, e.read)
    end

    ruby('--encoding', 'utf-8') do |w, r, e|
      w.puts "p '\u3042'"
      w.close
      assert_match(/invalid multibyte char/, e.read)
    end
  end

  def test_syntax_check
    ruby('-c', '-e', '1+1') do |w, r, e|
      assert_equal('Syntax OK', r.read.chomp)
    end
  end

  def test_invalid_option
    ruby('--foobarbazqux') do |w, r, e|
      assert_match(/invalid option --foobarbazqux/, e.read)
    end

    ruby("-\r", '-e', '') do |w, r, e|
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ruby("-\rx") do |w, r, e|
      assert_match(/invalid option -\\x0D  \(-h will show valid options\) \(RuntimeError\)/, e.read)
    end

    ruby("-\x01") do |w, r, e|
      assert_match(/invalid option -\\x01  \(-h will show valid options\) \(RuntimeError\)/, e.read)
    end

    ruby('-Z') do |w, r, e|
      assert_match(/invalid option -Z  \(-h will show valid options\) \(RuntimeError\)/, e.read)
    end
  end

  def test_rubyopt
    rubyopt_orig = ENV['RUBYOPT']

    ENV['RUBYOPT'] = ' - -'
    ruby do |w, r, e|
      w.close
      assert_equal('', e.read)
      assert_equal('', r.read)
    end

    ENV['RUBYOPT'] = '-e "p 1"'
    ruby do |w, r, e|
      assert_match(/invalid switch in RUBYOPT: -e \(RuntimeError\)/, e.read)
    end

    ENV['RUBYOPT'] = '-T1'
    ruby do |w, r, e|
      assert_match(/no program input from stdin allowed in tainted mode \(SecurityError\)/, e.read)
    end

    ENV['RUBYOPT'] = '-T4'
    ruby do |w, r, e|
    end

    ENV['RUBYOPT'] = '-KN -Eus-ascii'
    ruby('-KU', '-Eutf-8') do |w, r, e|
      w.puts "p '\u3042'"
      w.close
      assert_equal("\"\u3042\"", r.read.chomp.force_encoding(Encoding.find('utf-8')))
    end

  ensure
    if rubyopt_orig
      ENV['RUBYOPT'] = rubyopt_orig
    else
      ENV.delete('RUBYOPT')
    end
  end

  def test_search
    rubypath_orig = ENV['RUBYPATH']
    path_orig = ENV['PATH']

    t = Tempfile.new(["test_ruby_test_rubyoption", ".rb"])
    t.puts "p 1"
    t.close

    @verbose = $VERBOSE
    $VERBOSE = nil

    ENV['PATH'] = File.dirname(t.path)

    ruby('-S', File.basename(t.path)) do |w, r, e|
      assert_equal('', e.read)
      assert_equal('1', r.read.chomp)
    end

    ENV['RUBYPATH'] = File.dirname(t.path)

    ruby('-S', File.basename(t.path)) do |w, r, e|
      assert_equal('', e.read)
      assert_equal('1', r.read.chomp)
    end

  ensure
    if rubypath_orig
      ENV['RUBYPATH'] = rubypath_orig
    else
      ENV.delete('RUBYPATH')
    end
    if path_orig
      ENV['PATH'] = path_orig
    else
      ENV.delete('PATH')
    end
    t.close(true) if t
    $VERBOSE = @verbose
  end

  def test_shebang
    ruby do |w, r, e|
      w.print "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux\r\np 1\r\n"
      w.close
      assert_match(/Can't exec \/test_r_u_b_y_test_r_u_b_y_options_foobarbazqux \(fatal\)/, e.read)
      assert_equal('', r.read.chomp)
    end

    ruby do |w, r, e|
      w.print "#! /test_r_u_b_y_test_r_u_b_y_options_foobarbazqux -foo -bar\r\np 1\r\n"
      w.close
      assert_match(/Can't exec \/test_r_u_b_y_test_r_u_b_y_options_foobarbazqux \(fatal\)/, e.read)
      assert_equal('', r.read.chomp)
    end

    ruby do |w, r, e|
      w.print "#!ruby -KU -Eutf-8\r\np \"\u3042\"\r\n"
      w.close
      assert_equal('', e.read.chomp)
      assert_equal("\"\u3042\"", r.read.chomp.force_encoding(Encoding.find('utf-8')))
    end
  end

  def test_sflag
    ruby('-', '-abc', '-def=foo', '-ghi-jkl', '--', '-xyz') do |w, r, e|
      w.print "#!ruby -s\np [$abc, $def, $ghi_jkl, $xyz]\n"
      w.close
      assert_equal('', e.read)
      assert_equal('[true, "foo", true, nil]', r.read.chomp)
    end

    ruby('-', '-#') do |w, r, e|
      w.print "#!ruby -s\n"
      w.close
      assert_match(/invalid name for global variable - -# \(NameError\)/, e.read)
      assert_equal('', r.read.chomp)
    end

    ruby('-', '-#=foo') do |w, r, e|
      w.print "#!ruby -s\n"
      w.close
      assert_match(/invalid name for global variable - -# \(NameError\)/, e.read)
      assert_equal('', r.read.chomp)
    end
  end
end