1 /* Simulator for Analog Devices Blackfin processors. 2 3 Copyright (C) 2005-2015 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <signal.h> 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <unistd.h> 30 #include <sys/time.h> 31 32 #include "gdb/callback.h" 33 #include "gdb/signals.h" 34 #include "sim-main.h" 35 #include "sim-syscall.h" 36 #include "sim-hw.h" 37 38 #include "targ-vals.h" 39 40 /* The numbers here do not matter. They just need to be unique. They also 41 need not be static across releases -- they're used internally only. The 42 mapping from the Linux ABI to the CB values is in linux-targ-map.h. */ 43 #define CB_SYS_ioctl 201 44 #define CB_SYS_mmap2 202 45 #define CB_SYS_munmap 203 46 #define CB_SYS_dup2 204 47 #define CB_SYS_getuid 205 48 #define CB_SYS_getuid32 206 49 #define CB_SYS_getgid 207 50 #define CB_SYS_getgid32 208 51 #define CB_SYS_setuid 209 52 #define CB_SYS_setuid32 210 53 #define CB_SYS_setgid 211 54 #define CB_SYS_setgid32 212 55 #define CB_SYS_pread 213 56 #define CB_SYS__llseek 214 57 #define CB_SYS_getcwd 215 58 #define CB_SYS_stat64 216 59 #define CB_SYS_lstat64 217 60 #define CB_SYS_fstat64 218 61 #define CB_SYS_ftruncate64 219 62 #define CB_SYS_gettimeofday 220 63 #define CB_SYS_access 221 64 #include "linux-targ-map.h" 65 #include "linux-fixed-code.h" 66 67 #include "elf/common.h" 68 #include "elf/external.h" 69 #include "elf/internal.h" 70 #include "elf/bfin.h" 71 #include "elf-bfd.h" 72 73 #include "dv-bfin_cec.h" 74 #include "dv-bfin_mmu.h" 75 76 #ifndef HAVE_GETUID 77 # define getuid() 0 78 #endif 79 #ifndef HAVE_GETGID 80 # define getgid() 0 81 #endif 82 #ifndef HAVE_GETEUID 83 # define geteuid() 0 84 #endif 85 #ifndef HAVE_GETEGID 86 # define getegid() 0 87 #endif 88 #ifndef HAVE_SETUID 89 # define setuid(uid) -1 90 #endif 91 #ifndef HAVE_SETGID 92 # define setgid(gid) -1 93 #endif 94 95 static const char cb_linux_stat_map_32[] = 96 /* Linux kernel 32bit layout: */ 97 "st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:" 98 "space,2:st_size,4:st_blksize,4:st_blocks,4:st_atime,4:st_atimensec,4:" 99 "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:space,4"; 100 /* uClibc public ABI 32bit layout: 101 "st_dev,8:space,2:space,2:st_ino,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:" 102 "st_rdev,8:space,2:space,2:st_size,4:st_blksiez,4:st_blocks,4:st_atime,4:" 103 "st_atimensec,4:st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:space,4:" 104 "space,4"; */ 105 static const char cb_linux_stat_map_64[] = 106 "st_dev,8:space,4:space,4:st_mode,4:st_nlink,4:st_uid,4:st_gid,4:st_rdev,8:" 107 "space,4:st_size,8:st_blksize,4:st_blocks,8:st_atime,4:st_atimensec,4:" 108 "st_mtime,4:st_mtimensec,4:st_ctime,4:st_ctimensec,4:st_ino,8"; 109 static const char cb_libgloss_stat_map_32[] = 110 "st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2:st_rdev,2:" 111 "st_size,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:" 112 "space,4:st_blksize,4:st_blocks,4:space,8"; 113 static const char *stat_map_32, *stat_map_64; 114 115 /* Count the number of arguments in an argv. */ 116 static int 117 count_argc (const char * const *argv) 118 { 119 int i; 120 121 if (! argv) 122 return -1; 123 124 for (i = 0; argv[i] != NULL; ++i) 125 continue; 126 return i; 127 } 128 129 /* Simulate a monitor trap, put the result into r0 and errno into r1 130 return offset by which to adjust pc. */ 131 132 void 133 bfin_syscall (SIM_CPU *cpu) 134 { 135 SIM_DESC sd = CPU_STATE (cpu); 136 const char * const *argv = (void *)STATE_PROG_ARGV (sd); 137 host_callback *cb = STATE_CALLBACK (sd); 138 bu32 args[6]; 139 CB_SYSCALL sc; 140 char *p; 141 char _tbuf[1024 * 3], *tbuf = _tbuf, tstr[1024]; 142 int fmt_ret_hex = 0; 143 144 CB_SYSCALL_INIT (&sc); 145 146 if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT) 147 { 148 /* Linux syscall. */ 149 sc.func = PREG (0); 150 sc.arg1 = args[0] = DREG (0); 151 sc.arg2 = args[1] = DREG (1); 152 sc.arg3 = args[2] = DREG (2); 153 sc.arg4 = args[3] = DREG (3); 154 /*sc.arg5 =*/ args[4] = DREG (4); 155 /*sc.arg6 =*/ args[5] = DREG (5); 156 } 157 else 158 { 159 /* libgloss syscall. */ 160 sc.func = PREG (0); 161 sc.arg1 = args[0] = GET_LONG (DREG (0)); 162 sc.arg2 = args[1] = GET_LONG (DREG (0) + 4); 163 sc.arg3 = args[2] = GET_LONG (DREG (0) + 8); 164 sc.arg4 = args[3] = GET_LONG (DREG (0) + 12); 165 /*sc.arg5 =*/ args[4] = GET_LONG (DREG (0) + 16); 166 /*sc.arg6 =*/ args[5] = GET_LONG (DREG (0) + 20); 167 } 168 sc.p1 = (PTR) sd; 169 sc.p2 = (PTR) cpu; 170 sc.read_mem = sim_syscall_read_mem; 171 sc.write_mem = sim_syscall_write_mem; 172 173 /* Common cb_syscall() handles most functions. */ 174 switch (cb_target_to_host_syscall (cb, sc.func)) 175 { 176 case CB_SYS_exit: 177 tbuf += sprintf (tbuf, "exit(%i)", args[0]); 178 sim_engine_halt (sd, cpu, NULL, PCREG, sim_exited, sc.arg1); 179 180 #ifdef CB_SYS_argc 181 case CB_SYS_argc: 182 tbuf += sprintf (tbuf, "argc()"); 183 sc.result = count_argc (argv); 184 break; 185 case CB_SYS_argnlen: 186 { 187 tbuf += sprintf (tbuf, "argnlen(%u)", args[0]); 188 if (sc.arg1 < count_argc (argv)) 189 sc.result = strlen (argv[sc.arg1]); 190 else 191 sc.result = -1; 192 } 193 break; 194 case CB_SYS_argn: 195 { 196 tbuf += sprintf (tbuf, "argn(%u)", args[0]); 197 if (sc.arg1 < count_argc (argv)) 198 { 199 const char *argn = argv[sc.arg1]; 200 int len = strlen (argn); 201 int written = sc.write_mem (cb, &sc, sc.arg2, argn, len + 1); 202 if (written == len + 1) 203 sc.result = sc.arg2; 204 else 205 sc.result = -1; 206 } 207 else 208 sc.result = -1; 209 } 210 break; 211 #endif 212 213 case CB_SYS_gettimeofday: 214 { 215 struct timeval _tv, *tv = &_tv; 216 struct timezone _tz, *tz = &_tz; 217 218 tbuf += sprintf (tbuf, "gettimeofday(%#x, %#x)", args[0], args[1]); 219 220 if (sc.arg1 == 0) 221 tv = NULL; 222 if (sc.arg2 == 0) 223 tz = NULL; 224 sc.result = gettimeofday (tv, tz); 225 226 if (sc.result == 0) 227 { 228 bu32 t; 229 230 if (tv) 231 { 232 t = tv->tv_sec; 233 sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4); 234 t = tv->tv_usec; 235 sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4); 236 } 237 238 if (sc.arg2) 239 { 240 t = tz->tz_minuteswest; 241 sc.write_mem (cb, &sc, sc.arg1, (void *)&t, 4); 242 t = tz->tz_dsttime; 243 sc.write_mem (cb, &sc, sc.arg1 + 4, (void *)&t, 4); 244 } 245 } 246 else 247 goto sys_finish; 248 } 249 break; 250 251 case CB_SYS_ioctl: 252 /* XXX: hack just enough to get basic stdio w/uClibc ... */ 253 tbuf += sprintf (tbuf, "ioctl(%i, %#x, %u)", args[0], args[1], args[2]); 254 if (sc.arg2 == 0x5401) 255 { 256 sc.result = !isatty (sc.arg1); 257 sc.errcode = 0; 258 } 259 else 260 { 261 sc.result = -1; 262 sc.errcode = TARGET_EINVAL; 263 } 264 break; 265 266 case CB_SYS_mmap2: 267 { 268 static bu32 heap = BFIN_DEFAULT_MEM_SIZE / 2; 269 270 fmt_ret_hex = 1; 271 tbuf += sprintf (tbuf, "mmap2(%#x, %u, %#x, %#x, %i, %u)", 272 args[0], args[1], args[2], args[3], args[4], args[5]); 273 274 sc.errcode = 0; 275 276 if (sc.arg4 & 0x20 /*MAP_ANONYMOUS*/) 277 /* XXX: We don't handle zeroing, but default is all zeros. */; 278 else if (args[4] >= MAX_CALLBACK_FDS) 279 sc.errcode = TARGET_ENOSYS; 280 else 281 { 282 #ifdef HAVE_PREAD 283 char *data = xmalloc (sc.arg2); 284 285 /* XXX: Should add a cb->pread. */ 286 if (pread (cb->fdmap[args[4]], data, sc.arg2, args[5] << 12) == sc.arg2) 287 sc.write_mem (cb, &sc, heap, data, sc.arg2); 288 else 289 sc.errcode = TARGET_EINVAL; 290 291 free (data); 292 #else 293 sc.errcode = TARGET_ENOSYS; 294 #endif 295 } 296 297 if (sc.errcode) 298 { 299 sc.result = -1; 300 break; 301 } 302 303 sc.result = heap; 304 heap += sc.arg2; 305 /* Keep it page aligned. */ 306 heap = ALIGN (heap, 4096); 307 308 break; 309 } 310 311 case CB_SYS_munmap: 312 /* XXX: meh, just lie for mmap(). */ 313 tbuf += sprintf (tbuf, "munmap(%#x, %u)", args[0], args[1]); 314 sc.result = 0; 315 break; 316 317 case CB_SYS_dup2: 318 tbuf += sprintf (tbuf, "dup2(%i, %i)", args[0], args[1]); 319 if (sc.arg1 >= MAX_CALLBACK_FDS || sc.arg2 >= MAX_CALLBACK_FDS) 320 { 321 sc.result = -1; 322 sc.errcode = TARGET_EINVAL; 323 } 324 else 325 { 326 sc.result = dup2 (cb->fdmap[sc.arg1], cb->fdmap[sc.arg2]); 327 goto sys_finish; 328 } 329 break; 330 331 case CB_SYS__llseek: 332 tbuf += sprintf (tbuf, "llseek(%i, %u, %u, %#x, %u)", 333 args[0], args[1], args[2], args[3], args[4]); 334 sc.func = TARGET_LINUX_SYS_lseek; 335 if (sc.arg2) 336 { 337 sc.result = -1; 338 sc.errcode = TARGET_EINVAL; 339 } 340 else 341 { 342 sc.arg2 = sc.arg3; 343 sc.arg3 = args[4]; 344 cb_syscall (cb, &sc); 345 if (sc.result != -1) 346 { 347 bu32 z = 0; 348 sc.write_mem (cb, &sc, args[3], (void *)&sc.result, 4); 349 sc.write_mem (cb, &sc, args[3] + 4, (void *)&z, 4); 350 } 351 } 352 break; 353 354 /* XXX: Should add a cb->pread. */ 355 case CB_SYS_pread: 356 tbuf += sprintf (tbuf, "pread(%i, %#x, %u, %i)", 357 args[0], args[1], args[2], args[3]); 358 if (sc.arg1 >= MAX_CALLBACK_FDS) 359 { 360 sc.result = -1; 361 sc.errcode = TARGET_EINVAL; 362 } 363 else 364 { 365 long old_pos, read_result, read_errcode; 366 367 /* Get current filepos. */ 368 sc.func = TARGET_LINUX_SYS_lseek; 369 sc.arg2 = 0; 370 sc.arg3 = SEEK_CUR; 371 cb_syscall (cb, &sc); 372 if (sc.result == -1) 373 break; 374 old_pos = sc.result; 375 376 /* Move to the new pos. */ 377 sc.func = TARGET_LINUX_SYS_lseek; 378 sc.arg2 = args[3]; 379 sc.arg3 = SEEK_SET; 380 cb_syscall (cb, &sc); 381 if (sc.result == -1) 382 break; 383 384 /* Read the data. */ 385 sc.func = TARGET_LINUX_SYS_read; 386 sc.arg2 = args[1]; 387 sc.arg3 = args[2]; 388 cb_syscall (cb, &sc); 389 read_result = sc.result; 390 read_errcode = sc.errcode; 391 392 /* Move back to the old pos. */ 393 sc.func = TARGET_LINUX_SYS_lseek; 394 sc.arg2 = old_pos; 395 sc.arg3 = SEEK_SET; 396 cb_syscall (cb, &sc); 397 398 sc.result = read_result; 399 sc.errcode = read_errcode; 400 } 401 break; 402 403 case CB_SYS_getcwd: 404 tbuf += sprintf (tbuf, "getcwd(%#x, %u)", args[0], args[1]); 405 406 p = alloca (sc.arg2); 407 if (getcwd (p, sc.arg2) == NULL) 408 { 409 sc.result = -1; 410 sc.errcode = TARGET_EINVAL; 411 } 412 else 413 { 414 sc.write_mem (cb, &sc, sc.arg1, p, sc.arg2); 415 sc.result = sc.arg1; 416 } 417 break; 418 419 case CB_SYS_stat64: 420 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 421 strcpy (tstr, "???"); 422 tbuf += sprintf (tbuf, "stat64(%#x:\"%s\", %u)", args[0], tstr, args[1]); 423 cb->stat_map = stat_map_64; 424 sc.func = TARGET_LINUX_SYS_stat; 425 cb_syscall (cb, &sc); 426 cb->stat_map = stat_map_32; 427 break; 428 case CB_SYS_lstat64: 429 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 430 strcpy (tstr, "???"); 431 tbuf += sprintf (tbuf, "lstat64(%#x:\"%s\", %u)", args[0], tstr, args[1]); 432 cb->stat_map = stat_map_64; 433 sc.func = TARGET_LINUX_SYS_lstat; 434 cb_syscall (cb, &sc); 435 cb->stat_map = stat_map_32; 436 break; 437 case CB_SYS_fstat64: 438 tbuf += sprintf (tbuf, "fstat64(%#x, %u)", args[0], args[1]); 439 cb->stat_map = stat_map_64; 440 sc.func = TARGET_LINUX_SYS_fstat; 441 cb_syscall (cb, &sc); 442 cb->stat_map = stat_map_32; 443 break; 444 445 case CB_SYS_ftruncate64: 446 tbuf += sprintf (tbuf, "ftruncate64(%u, %u)", args[0], args[1]); 447 sc.func = TARGET_LINUX_SYS_ftruncate; 448 cb_syscall (cb, &sc); 449 break; 450 451 case CB_SYS_getuid: 452 case CB_SYS_getuid32: 453 tbuf += sprintf (tbuf, "getuid()"); 454 sc.result = getuid (); 455 goto sys_finish; 456 case CB_SYS_getgid: 457 case CB_SYS_getgid32: 458 tbuf += sprintf (tbuf, "getgid()"); 459 sc.result = getgid (); 460 goto sys_finish; 461 case CB_SYS_setuid: 462 sc.arg1 &= 0xffff; 463 case CB_SYS_setuid32: 464 tbuf += sprintf (tbuf, "setuid(%u)", args[0]); 465 sc.result = setuid (sc.arg1); 466 goto sys_finish; 467 case CB_SYS_setgid: 468 sc.arg1 &= 0xffff; 469 case CB_SYS_setgid32: 470 tbuf += sprintf (tbuf, "setgid(%u)", args[0]); 471 sc.result = setgid (sc.arg1); 472 goto sys_finish; 473 474 case CB_SYS_getpid: 475 tbuf += sprintf (tbuf, "getpid()"); 476 sc.result = getpid (); 477 goto sys_finish; 478 case CB_SYS_kill: 479 tbuf += sprintf (tbuf, "kill(%u, %i)", args[0], args[1]); 480 /* Only let the app kill itself. */ 481 if (sc.arg1 != getpid ()) 482 { 483 sc.result = -1; 484 sc.errcode = TARGET_EPERM; 485 } 486 else 487 { 488 #ifdef HAVE_KILL 489 sc.result = kill (sc.arg1, sc.arg2); 490 goto sys_finish; 491 #else 492 sc.result = -1; 493 sc.errcode = TARGET_ENOSYS; 494 #endif 495 } 496 break; 497 498 case CB_SYS_open: 499 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 500 strcpy (tstr, "???"); 501 tbuf += sprintf (tbuf, "open(%#x:\"%s\", %#x, %o)", 502 args[0], tstr, args[1], args[2]); 503 goto case_default; 504 case CB_SYS_close: 505 tbuf += sprintf (tbuf, "close(%i)", args[0]); 506 goto case_default; 507 case CB_SYS_read: 508 tbuf += sprintf (tbuf, "read(%i, %#x, %u)", args[0], args[1], args[2]); 509 goto case_default; 510 case CB_SYS_write: 511 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1])) 512 strcpy (tstr, "???"); 513 tbuf += sprintf (tbuf, "write(%i, %#x:\"%s\", %u)", 514 args[0], args[1], tstr, args[2]); 515 goto case_default; 516 case CB_SYS_lseek: 517 tbuf += sprintf (tbuf, "lseek(%i, %i, %i)", args[0], args[1], args[2]); 518 goto case_default; 519 case CB_SYS_unlink: 520 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 521 strcpy (tstr, "???"); 522 tbuf += sprintf (tbuf, "unlink(%#x:\"%s\")", args[0], tstr); 523 goto case_default; 524 case CB_SYS_truncate: 525 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 526 strcpy (tstr, "???"); 527 tbuf += sprintf (tbuf, "truncate(%#x:\"%s\", %i)", args[0], tstr, args[1]); 528 goto case_default; 529 case CB_SYS_ftruncate: 530 tbuf += sprintf (tbuf, "ftruncate(%i, %i)", args[0], args[1]); 531 goto case_default; 532 case CB_SYS_rename: 533 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 534 strcpy (tstr, "???"); 535 tbuf += sprintf (tbuf, "rename(%#x:\"%s\", ", args[0], tstr); 536 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[1])) 537 strcpy (tstr, "???"); 538 tbuf += sprintf (tbuf, "%#x:\"%s\")", args[1], tstr); 539 goto case_default; 540 case CB_SYS_stat: 541 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 542 strcpy (tstr, "???"); 543 tbuf += sprintf (tbuf, "stat(%#x:\"%s\", %#x)", args[0], tstr, args[1]); 544 goto case_default; 545 case CB_SYS_fstat: 546 tbuf += sprintf (tbuf, "fstat(%i, %#x)", args[0], args[1]); 547 goto case_default; 548 case CB_SYS_lstat: 549 if (cb_get_string (cb, &sc, tstr, sizeof (tstr), args[0])) 550 strcpy (tstr, "???"); 551 tbuf += sprintf (tbuf, "lstat(%#x:\"%s\", %#x)", args[0], tstr, args[1]); 552 goto case_default; 553 case CB_SYS_pipe: 554 tbuf += sprintf (tbuf, "pipe(%#x, %#x)", args[0], args[1]); 555 goto case_default; 556 557 default: 558 tbuf += sprintf (tbuf, "???_%i(%#x, %#x, %#x, %#x, %#x, %#x)", sc.func, 559 args[0], args[1], args[2], args[3], args[4], args[5]); 560 case_default: 561 cb_syscall (cb, &sc); 562 break; 563 564 sys_finish: 565 if (sc.result == -1) 566 { 567 cb->last_errno = errno; 568 sc.errcode = cb->get_errno (cb); 569 } 570 } 571 572 TRACE_EVENTS (cpu, "syscall_%i(%#x, %#x, %#x, %#x, %#x, %#x) = %li (error = %i)", 573 sc.func, args[0], args[1], args[2], args[3], args[4], args[5], 574 sc.result, sc.errcode); 575 576 tbuf += sprintf (tbuf, " = "); 577 if (STATE_ENVIRONMENT (sd) == USER_ENVIRONMENT) 578 { 579 if (sc.result == -1) 580 { 581 tbuf += sprintf (tbuf, "-1 (error = %i)", sc.errcode); 582 if (sc.errcode == cb_host_to_target_errno (cb, ENOSYS)) 583 { 584 sim_io_eprintf (sd, "bfin-sim: %#x: unimplemented syscall %i\n", 585 PCREG, sc.func); 586 } 587 SET_DREG (0, -sc.errcode); 588 } 589 else 590 { 591 if (fmt_ret_hex) 592 tbuf += sprintf (tbuf, "%#lx", sc.result); 593 else 594 tbuf += sprintf (tbuf, "%lu", sc.result); 595 SET_DREG (0, sc.result); 596 } 597 } 598 else 599 { 600 tbuf += sprintf (tbuf, "%lu (error = %i)", sc.result, sc.errcode); 601 SET_DREG (0, sc.result); 602 SET_DREG (1, sc.result2); 603 SET_DREG (2, sc.errcode); 604 } 605 606 TRACE_SYSCALL (cpu, "%s", _tbuf); 607 } 608 609 /* Execute a single instruction. */ 610 611 static sim_cia 612 step_once (SIM_CPU *cpu) 613 { 614 SIM_DESC sd = CPU_STATE (cpu); 615 bu32 insn_len, oldpc = PCREG; 616 int i; 617 bool ssstep; 618 619 if (TRACE_ANY_P (cpu)) 620 trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu), 621 NULL, 0, " "); /* Use a space for gcc warnings. */ 622 623 /* Handle hardware single stepping when lower than EVT3, and when SYSCFG 624 has already had the SSSTEP bit enabled. */ 625 ssstep = false; 626 if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT 627 && (SYSCFGREG & SYSCFG_SSSTEP)) 628 { 629 int ivg = cec_get_ivg (cpu); 630 if (ivg == -1 || ivg > 3) 631 ssstep = true; 632 } 633 634 #if 0 635 /* XXX: Is this what happens on the hardware ? */ 636 if (cec_get_ivg (cpu) == EVT_EMU) 637 cec_return (cpu, EVT_EMU); 638 #endif 639 640 BFIN_CPU_STATE.did_jump = false; 641 642 insn_len = interp_insn_bfin (cpu, oldpc); 643 644 /* If we executed this insn successfully, then we always decrement 645 the loop counter. We don't want to update the PC though if the 646 last insn happened to be a change in code flow (jump/etc...). */ 647 if (!BFIN_CPU_STATE.did_jump) 648 SET_PCREG (hwloop_get_next_pc (cpu, oldpc, insn_len)); 649 for (i = 1; i >= 0; --i) 650 if (LCREG (i) && oldpc == LBREG (i)) 651 { 652 SET_LCREG (i, LCREG (i) - 1); 653 if (LCREG (i)) 654 break; 655 } 656 657 ++ PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)); 658 659 /* Handle hardware single stepping only if we're still lower than EVT3. 660 XXX: May not be entirely correct wrt EXCPT insns. */ 661 if (ssstep) 662 { 663 int ivg = cec_get_ivg (cpu); 664 if (ivg == -1 || ivg > 3) 665 { 666 INSN_LEN = 0; 667 cec_exception (cpu, VEC_STEP); 668 } 669 } 670 671 return oldpc; 672 } 673 674 void 675 sim_engine_run (SIM_DESC sd, 676 int next_cpu_nr, /* ignore */ 677 int nr_cpus, /* ignore */ 678 int siggnal) /* ignore */ 679 { 680 bu32 ticks; 681 SIM_CPU *cpu; 682 683 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 684 685 cpu = STATE_CPU (sd, 0); 686 687 while (1) 688 { 689 step_once (cpu); 690 /* Process any events -- can't use tickn because it may 691 advance right over the next event. */ 692 for (ticks = 0; ticks < CYCLE_DELAY; ++ticks) 693 if (sim_events_tick (sd)) 694 sim_events_process (sd); 695 } 696 } 697 698 /* Cover function of sim_state_free to free the cpu buffers as well. */ 699 700 static void 701 free_state (SIM_DESC sd) 702 { 703 if (STATE_MODULES (sd) != NULL) 704 sim_module_uninstall (sd); 705 sim_cpu_free_all (sd); 706 sim_state_free (sd); 707 } 708 709 /* Create an instance of the simulator. */ 710 711 static void 712 bfin_initialize_cpu (SIM_DESC sd, SIM_CPU *cpu) 713 { 714 memset (&cpu->state, 0, sizeof (cpu->state)); 715 716 PROFILE_TOTAL_INSN_COUNT (CPU_PROFILE_DATA (cpu)) = 0; 717 718 bfin_model_cpu_init (sd, cpu); 719 720 /* Set default stack to top of scratch pad. */ 721 SET_SPREG (BFIN_DEFAULT_MEM_SIZE); 722 SET_KSPREG (BFIN_DEFAULT_MEM_SIZE); 723 SET_USPREG (BFIN_DEFAULT_MEM_SIZE); 724 725 /* This is what the hardware likes. */ 726 SET_SYSCFGREG (0x30); 727 } 728 729 SIM_DESC 730 sim_open (SIM_OPEN_KIND kind, host_callback *callback, 731 struct bfd *abfd, char **argv) 732 { 733 char c; 734 int i; 735 SIM_DESC sd = sim_state_alloc (kind, callback); 736 737 /* The cpu data is kept in a separately allocated chunk of memory. */ 738 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) 739 { 740 free_state (sd); 741 return 0; 742 } 743 744 { 745 /* XXX: Only first core gets profiled ? */ 746 SIM_CPU *cpu = STATE_CPU (sd, 0); 747 STATE_WATCHPOINTS (sd)->pc = &PCREG; 748 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PCREG); 749 } 750 751 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 752 { 753 free_state (sd); 754 return 0; 755 } 756 757 /* XXX: Default to the Virtual environment. */ 758 if (STATE_ENVIRONMENT (sd) == ALL_ENVIRONMENT) 759 STATE_ENVIRONMENT (sd) = VIRTUAL_ENVIRONMENT; 760 761 /* These options override any module options. 762 Obviously ambiguity should be avoided, however the caller may wish to 763 augment the meaning of an option. */ 764 #define e_sim_add_option_table(sd, options) \ 765 do { \ 766 extern const OPTION options[]; \ 767 sim_add_option_table (sd, NULL, options); \ 768 } while (0) 769 e_sim_add_option_table (sd, bfin_mmu_options); 770 e_sim_add_option_table (sd, bfin_mach_options); 771 772 /* getopt will print the error message so we just have to exit if this fails. 773 FIXME: Hmmm... in the case of gdb we need getopt to call 774 print_filtered. */ 775 if (sim_parse_args (sd, argv) != SIM_RC_OK) 776 { 777 free_state (sd); 778 return 0; 779 } 780 781 /* Allocate external memory if none specified by user. 782 Use address 4 here in case the user wanted address 0 unmapped. */ 783 if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0) 784 { 785 bu16 emuexcpt = 0x25; 786 sim_do_commandf (sd, "memory-size 0x%lx", BFIN_DEFAULT_MEM_SIZE); 787 sim_write (sd, 0, (void *)&emuexcpt, 2); 788 } 789 790 /* Check for/establish the a reference program image. */ 791 if (sim_analyze_program (sd, 792 (STATE_PROG_ARGV (sd) != NULL 793 ? *STATE_PROG_ARGV (sd) 794 : NULL), abfd) != SIM_RC_OK) 795 { 796 free_state (sd); 797 return 0; 798 } 799 800 /* Establish any remaining configuration options. */ 801 if (sim_config (sd) != SIM_RC_OK) 802 { 803 free_state (sd); 804 return 0; 805 } 806 807 if (sim_post_argv_init (sd) != SIM_RC_OK) 808 { 809 free_state (sd); 810 return 0; 811 } 812 813 /* CPU specific initialization. */ 814 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 815 { 816 SIM_CPU *cpu = STATE_CPU (sd, i); 817 bfin_initialize_cpu (sd, cpu); 818 } 819 820 return sd; 821 } 822 823 void 824 sim_close (SIM_DESC sd, int quitting) 825 { 826 sim_module_uninstall (sd); 827 } 828 829 /* Some utils don't like having a NULL environ. */ 830 static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL }; 831 832 static bu32 fdpic_load_offset; 833 834 static bool 835 bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp, 836 bu32 *elf_addrs, char **ldso_path) 837 { 838 bool ret; 839 int i; 840 841 Elf_Internal_Ehdr *iehdr; 842 Elf32_External_Ehdr ehdr; 843 Elf_Internal_Phdr *phdrs; 844 unsigned char *data; 845 long phdr_size; 846 int phdrc; 847 bu32 nsegs; 848 849 bu32 max_load_addr; 850 851 unsigned char null[4] = { 0, 0, 0, 0 }; 852 853 ret = false; 854 *ldso_path = NULL; 855 856 /* See if this an FDPIC ELF. */ 857 phdrs = NULL; 858 if (!abfd) 859 goto skip_fdpic_init; 860 if (bfd_seek (abfd, 0, SEEK_SET) != 0) 861 goto skip_fdpic_init; 862 if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr)) 863 goto skip_fdpic_init; 864 iehdr = elf_elfheader (abfd); 865 if (!(iehdr->e_flags & EF_BFIN_FDPIC)) 866 goto skip_fdpic_init; 867 868 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 869 sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n", 870 bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]); 871 872 /* Grab the Program Headers to set up the loadsegs on the stack. */ 873 phdr_size = bfd_get_elf_phdr_upper_bound (abfd); 874 if (phdr_size == -1) 875 goto skip_fdpic_init; 876 phdrs = xmalloc (phdr_size); 877 phdrc = bfd_get_elf_phdrs (abfd, phdrs); 878 if (phdrc == -1) 879 goto skip_fdpic_init; 880 881 /* Push the Ehdr onto the stack. */ 882 *sp -= sizeof (ehdr); 883 elf_addrs[3] = *sp; 884 sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr)); 885 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 886 sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp); 887 888 /* Since we're relocating things ourselves, we need to relocate 889 the start address as well. */ 890 elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset; 891 892 /* And the Exec's Phdrs onto the stack. */ 893 if (STATE_PROG_BFD (sd) == abfd) 894 { 895 elf_addrs[4] = elf_addrs[0]; 896 897 phdr_size = iehdr->e_phentsize * iehdr->e_phnum; 898 if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0) 899 goto skip_fdpic_init; 900 data = xmalloc (phdr_size); 901 if (bfd_bread (data, phdr_size, abfd) != phdr_size) 902 goto skip_fdpic_init; 903 *sp -= phdr_size; 904 elf_addrs[1] = *sp; 905 elf_addrs[2] = phdrc; 906 sim_write (sd, *sp, data, phdr_size); 907 free (data); 908 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 909 sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp); 910 } 911 912 /* Now push all the loadsegs. */ 913 nsegs = 0; 914 max_load_addr = 0; 915 for (i = phdrc; i >= 0; --i) 916 if (phdrs[i].p_type == PT_LOAD) 917 { 918 Elf_Internal_Phdr *p = &phdrs[i]; 919 bu32 paddr, vaddr, memsz, filesz; 920 921 paddr = p->p_paddr + fdpic_load_offset; 922 vaddr = p->p_vaddr; 923 memsz = p->p_memsz; 924 filesz = p->p_filesz; 925 926 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 927 sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n", 928 i, vaddr, paddr, filesz, memsz); 929 930 data = xmalloc (memsz); 931 if (memsz != filesz) 932 memset (data + filesz, 0, memsz - filesz); 933 934 if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0 935 && bfd_bread (data, filesz, abfd) == filesz) 936 sim_write (sd, paddr, data, memsz); 937 938 free (data); 939 940 max_load_addr = MAX (paddr + memsz, max_load_addr); 941 942 *sp -= 12; 943 sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */ 944 sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */ 945 sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */ 946 ++nsegs; 947 } 948 else if (phdrs[i].p_type == PT_DYNAMIC) 949 { 950 elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset; 951 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 952 sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]); 953 } 954 else if (phdrs[i].p_type == PT_INTERP) 955 { 956 uint32_t off = phdrs[i].p_offset; 957 uint32_t len = phdrs[i].p_filesz; 958 959 *ldso_path = xmalloc (len); 960 if (bfd_seek (abfd, off, SEEK_SET) != 0 961 || bfd_bread (*ldso_path, len, abfd) != len) 962 { 963 free (*ldso_path); 964 *ldso_path = NULL; 965 } 966 else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 967 sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path); 968 } 969 970 /* Update the load offset with a few extra pages. */ 971 fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000); 972 fdpic_load_offset += 0x10000; 973 974 /* Push the summary loadmap info onto the stack last. */ 975 *sp -= 4; 976 sim_write (sd, *sp+0, null, 2); /* loadmap.version */ 977 sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */ 978 979 ret = true; 980 skip_fdpic_init: 981 free (phdrs); 982 983 return ret; 984 } 985 986 static void 987 bfin_user_init (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, 988 const char * const *argv, const char * const *env) 989 { 990 /* XXX: Missing host -> target endian ... */ 991 /* Linux starts the user app with the stack: 992 argc 993 argv[0] -- pointers to the actual strings 994 argv[1..N] 995 NULL 996 env[0] 997 env[1..N] 998 NULL 999 auxvt[0].type -- ELF Auxiliary Vector Table 1000 auxvt[0].value 1001 auxvt[1..N] 1002 AT_NULL 1003 0 1004 argv[0..N][0..M] -- actual argv/env strings 1005 env[0..N][0..M] 1006 FDPIC loadmaps -- for FDPIC apps 1007 So set things up the same way. */ 1008 int i, argc, envc; 1009 bu32 argv_flat, env_flat; 1010 1011 bu32 sp, sp_flat; 1012 1013 /* start, at_phdr, at_phnum, at_base, at_entry, pt_dynamic */ 1014 bu32 elf_addrs[6]; 1015 bu32 auxvt; 1016 bu32 exec_loadmap, ldso_loadmap; 1017 char *ldso_path; 1018 1019 unsigned char null[4] = { 0, 0, 0, 0 }; 1020 1021 host_callback *cb = STATE_CALLBACK (sd); 1022 1023 elf_addrs[0] = elf_addrs[4] = bfd_get_start_address (abfd); 1024 elf_addrs[1] = elf_addrs[2] = elf_addrs[3] = elf_addrs[5] = 0; 1025 1026 /* Keep the load addresses consistent between runs. Also make sure we make 1027 space for the fixed code region (part of the Blackfin Linux ABI). */ 1028 fdpic_load_offset = 0x1000; 1029 1030 /* First try to load this as an FDPIC executable. */ 1031 sp = SPREG; 1032 if (!bfin_fdpic_load (sd, cpu, STATE_PROG_BFD (sd), &sp, elf_addrs, &ldso_path)) 1033 goto skip_fdpic_init; 1034 exec_loadmap = sp; 1035 1036 /* If that worked, then load the fixed code region. We only do this for 1037 FDPIC ELFs atm because they are PIEs and let us relocate them without 1038 manual fixups. FLAT files however require location processing which 1039 we do not do ourselves, and they link with a VMA of 0. */ 1040 sim_write (sd, 0x400, bfin_linux_fixed_code, sizeof (bfin_linux_fixed_code)); 1041 1042 /* If the FDPIC needs an interpreter, then load it up too. */ 1043 if (ldso_path) 1044 { 1045 const char *ldso_full_path = concat (simulator_sysroot, ldso_path, NULL); 1046 struct bfd *ldso_bfd; 1047 1048 ldso_bfd = bfd_openr (ldso_full_path, STATE_TARGET (sd)); 1049 if (!ldso_bfd) 1050 { 1051 sim_io_eprintf (sd, "bfin-sim: bfd open failed: %s\n", ldso_full_path); 1052 goto static_fdpic; 1053 } 1054 if (!bfd_check_format (ldso_bfd, bfd_object)) 1055 sim_io_eprintf (sd, "bfin-sim: bfd format not valid: %s\n", ldso_full_path); 1056 bfd_set_arch_info (ldso_bfd, STATE_ARCHITECTURE (sd)); 1057 1058 if (!bfin_fdpic_load (sd, cpu, ldso_bfd, &sp, elf_addrs, &ldso_path)) 1059 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso failed to load: %s\n", ldso_full_path); 1060 if (ldso_path) 1061 sim_io_eprintf (sd, "bfin-sim: FDPIC ldso (%s) needs an interpreter (%s) !?\n", 1062 ldso_full_path, ldso_path); 1063 1064 ldso_loadmap = sp; 1065 } 1066 else 1067 static_fdpic: 1068 ldso_loadmap = 0; 1069 1070 /* Finally setup the registers required by the FDPIC ABI. */ 1071 SET_DREG (7, 0); /* Zero out FINI funcptr -- ldso will set this up. */ 1072 SET_PREG (0, exec_loadmap); /* Exec loadmap addr. */ 1073 SET_PREG (1, ldso_loadmap); /* Interp loadmap addr. */ 1074 SET_PREG (2, elf_addrs[5]); /* PT_DYNAMIC map addr. */ 1075 1076 auxvt = 1; 1077 SET_SPREG (sp); 1078 skip_fdpic_init: 1079 sim_pc_set (cpu, elf_addrs[0]); 1080 1081 /* Figure out how much storage the argv/env strings need. */ 1082 argc = count_argc (argv); 1083 if (argc == -1) 1084 argc = 0; 1085 argv_flat = argc; /* NUL bytes */ 1086 for (i = 0; i < argc; ++i) 1087 argv_flat += strlen (argv[i]); 1088 1089 if (!env) 1090 env = simple_env; 1091 envc = count_argc (env); 1092 env_flat = envc; /* NUL bytes */ 1093 for (i = 0; i < envc; ++i) 1094 env_flat += strlen (env[i]); 1095 1096 /* Push the Auxiliary Vector Table between argv/env and actual strings. */ 1097 sp_flat = sp = ALIGN (SPREG - argv_flat - env_flat - 4, 4); 1098 if (auxvt) 1099 { 1100 # define AT_PUSH(at, val) \ 1101 auxvt_size += 8; \ 1102 sp -= 4; \ 1103 auxvt = (val); \ 1104 sim_write (sd, sp, (void *)&auxvt, 4); \ 1105 sp -= 4; \ 1106 auxvt = (at); \ 1107 sim_write (sd, sp, (void *)&auxvt, 4) 1108 unsigned int egid = getegid (), gid = getgid (); 1109 unsigned int euid = geteuid (), uid = getuid (); 1110 bu32 auxvt_size = 0; 1111 AT_PUSH (AT_NULL, 0); 1112 AT_PUSH (AT_SECURE, egid != gid || euid != uid); 1113 AT_PUSH (AT_EGID, egid); 1114 AT_PUSH (AT_GID, gid); 1115 AT_PUSH (AT_EUID, euid); 1116 AT_PUSH (AT_UID, uid); 1117 AT_PUSH (AT_ENTRY, elf_addrs[4]); 1118 AT_PUSH (AT_FLAGS, 0); 1119 AT_PUSH (AT_BASE, elf_addrs[3]); 1120 AT_PUSH (AT_PHNUM, elf_addrs[2]); 1121 AT_PUSH (AT_PHENT, sizeof (Elf32_External_Phdr)); 1122 AT_PUSH (AT_PHDR, elf_addrs[1]); 1123 AT_PUSH (AT_CLKTCK, 100); /* XXX: This ever not 100 ? */ 1124 AT_PUSH (AT_PAGESZ, 4096); 1125 AT_PUSH (AT_HWCAP, 0); 1126 #undef AT_PUSH 1127 } 1128 SET_SPREG (sp); 1129 1130 /* Push the argc/argv/env after the auxvt. */ 1131 sp -= ((1 + argc + 1 + envc + 1) * 4); 1132 SET_SPREG (sp); 1133 1134 /* First push the argc value. */ 1135 sim_write (sd, sp, (void *)&argc, 4); 1136 sp += 4; 1137 1138 /* Then the actual argv strings so we know where to point argv[]. */ 1139 for (i = 0; i < argc; ++i) 1140 { 1141 unsigned len = strlen (argv[i]) + 1; 1142 sim_write (sd, sp_flat, (void *)argv[i], len); 1143 sim_write (sd, sp, (void *)&sp_flat, 4); 1144 sp_flat += len; 1145 sp += 4; 1146 } 1147 sim_write (sd, sp, null, 4); 1148 sp += 4; 1149 1150 /* Then the actual env strings so we know where to point env[]. */ 1151 for (i = 0; i < envc; ++i) 1152 { 1153 unsigned len = strlen (env[i]) + 1; 1154 sim_write (sd, sp_flat, (void *)env[i], len); 1155 sim_write (sd, sp, (void *)&sp_flat, 4); 1156 sp_flat += len; 1157 sp += 4; 1158 } 1159 1160 /* Set some callbacks. */ 1161 cb->syscall_map = cb_linux_syscall_map; 1162 cb->errno_map = cb_linux_errno_map; 1163 cb->open_map = cb_linux_open_map; 1164 cb->signal_map = cb_linux_signal_map; 1165 cb->stat_map = stat_map_32 = cb_linux_stat_map_32; 1166 stat_map_64 = cb_linux_stat_map_64; 1167 } 1168 1169 static void 1170 bfin_os_init (SIM_DESC sd, SIM_CPU *cpu, const char * const *argv) 1171 { 1172 /* Pass the command line via a string in R0 like Linux expects. */ 1173 int i; 1174 bu8 byte; 1175 bu32 cmdline = BFIN_L1_SRAM_SCRATCH; 1176 1177 SET_DREG (0, cmdline); 1178 if (argv && argv[0]) 1179 { 1180 i = 1; 1181 byte = ' '; 1182 while (argv[i]) 1183 { 1184 bu32 len = strlen (argv[i]); 1185 sim_write (sd, cmdline, (void *)argv[i], len); 1186 cmdline += len; 1187 sim_write (sd, cmdline, &byte, 1); 1188 ++cmdline; 1189 ++i; 1190 } 1191 } 1192 byte = 0; 1193 sim_write (sd, cmdline, &byte, 1); 1194 } 1195 1196 static void 1197 bfin_virtual_init (SIM_DESC sd, SIM_CPU *cpu) 1198 { 1199 host_callback *cb = STATE_CALLBACK (sd); 1200 1201 cb->stat_map = stat_map_32 = cb_libgloss_stat_map_32; 1202 stat_map_64 = NULL; 1203 } 1204 1205 SIM_RC 1206 sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 1207 char **argv, char **env) 1208 { 1209 SIM_CPU *cpu = STATE_CPU (sd, 0); 1210 SIM_ADDR addr; 1211 1212 /* Set the PC. */ 1213 if (abfd != NULL) 1214 addr = bfd_get_start_address (abfd); 1215 else 1216 addr = 0; 1217 sim_pc_set (cpu, addr); 1218 1219 /* Standalone mode (i.e. `bfin-...-run`) will take care of the argv 1220 for us in sim_open() -> sim_parse_args(). But in debug mode (i.e. 1221 'target sim' with `bfin-...-gdb`), we need to handle it. */ 1222 if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) 1223 { 1224 freeargv (STATE_PROG_ARGV (sd)); 1225 STATE_PROG_ARGV (sd) = dupargv (argv); 1226 } 1227 1228 switch (STATE_ENVIRONMENT (sd)) 1229 { 1230 case USER_ENVIRONMENT: 1231 bfin_user_init (sd, cpu, abfd, (void *)argv, (void *)env); 1232 break; 1233 case OPERATING_ENVIRONMENT: 1234 bfin_os_init (sd, cpu, (void *)argv); 1235 break; 1236 default: 1237 bfin_virtual_init (sd, cpu); 1238 break; 1239 } 1240 1241 return SIM_RC_OK; 1242 } 1243