Changes in uspace/app/sysinst/sysinst.c [c24b0dcb:61f28c4] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/sysinst/sysinst.c
rc24b0dcb r61f28c4 1 1 /* 2 * Copyright (c) 20 18Jiri Svoboda2 * Copyright (c) 2025 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 41 41 #include <errno.h> 42 42 #include <fdisk.h> 43 #include <futil.h> 44 #include <gfx/render.h> 45 #include <io/log.h> 43 46 #include <loc.h> 44 47 #include <stdio.h> … … 46 49 #include <str.h> 47 50 #include <str_error.h> 51 #include <system.h> 52 #include <ui/msgdialog.h> 53 #include <ui/ui.h> 54 #include <ui/window.h> 48 55 #include <vfs/vfs.h> 49 56 #include <vol.h> 50 57 51 #include "futil.h"52 58 #include "grub.h" 53 59 #include "rdimg.h" 54 60 #include "volume.h" 61 #include "sysinst.h" 62 63 #define NAME "sysinst" 55 64 56 65 /** Device to install to … … 62 71 * in Grub notation). 63 72 */ 64 #define DEFAULT_DEV "devices/\\hw\\sys\\00:01.0\\ata-c1\\d0" 73 #define DEFAULT_DEV_0 "devices/\\hw\\sys\\00:01.1\\c0d0" 74 #define DEFAULT_DEV_1 "devices/\\hw\\sys\\ide1\\c0d0" 75 #define DEFAULT_DEV_2 "devices/\\hw\\sys\\00:01.0\\ide1\\c0d0" 65 76 //#define DEFAULT_DEV "devices/\\hw\\pci0\\00:01.2\\uhci_rh\\usb01_a1\\mass-storage0\\l0" 66 77 /** Volume label for the new file system */ … … 79 90 #define BOOT_BLOCK_IDX 0 /* MBR */ 80 91 92 #define CFG_FILES_SRC "/cfg" 93 #define CFG_FILES_DEST MOUNT_POINT "/cfg" 94 95 static const char *default_devs[] = { 96 DEFAULT_DEV_0, 97 DEFAULT_DEV_1, 98 DEFAULT_DEV_2, 99 NULL 100 }; 101 81 102 static const char *sys_dirs[] = { 82 103 "/cfg", 83 "/data" 104 "/data", 105 NULL 84 106 }; 85 107 86 /** Label the destination device. 87 * 108 static fibril_mutex_t shutdown_lock; 109 static fibril_condvar_t shutdown_cv; 110 static bool shutdown_stopped; 111 static bool shutdown_failed; 112 113 static void sysinst_shutdown_complete(void *); 114 static void sysinst_shutdown_failed(void *); 115 116 static system_cb_t sysinst_system_cb = { 117 .shutdown_complete = sysinst_shutdown_complete, 118 .shutdown_failed = sysinst_shutdown_failed 119 }; 120 121 static void wnd_close(ui_window_t *, void *); 122 static errno_t bg_wnd_paint(ui_window_t *, void *); 123 124 static ui_window_cb_t bg_window_cb = { 125 .close = wnd_close, 126 .paint = bg_wnd_paint 127 }; 128 129 static ui_window_cb_t progress_window_cb = { 130 .close = wnd_close 131 }; 132 133 static void sysinst_confirm_button(ui_msg_dialog_t *, void *, unsigned); 134 static void sysinst_confirm_close(ui_msg_dialog_t *, void *); 135 136 static ui_msg_dialog_cb_t sysinst_confirm_cb = { 137 .button = sysinst_confirm_button, 138 .close = sysinst_confirm_close 139 }; 140 141 static errno_t sysinst_restart_dlg_create(sysinst_t *); 142 static void sysinst_restart_dlg_button(ui_msg_dialog_t *, void *, unsigned); 143 static void sysinst_restart_dlg_close(ui_msg_dialog_t *, void *); 144 145 static ui_msg_dialog_cb_t sysinst_restart_dlg_cb = { 146 .button = sysinst_restart_dlg_button, 147 .close = sysinst_restart_dlg_close 148 }; 149 150 static int sysinst_start(sysinst_t *); 151 static errno_t sysinst_restart(sysinst_t *); 152 static void sysinst_progress_destroy(sysinst_progress_t *); 153 static void sysinst_action(sysinst_t *, const char *); 154 static void sysinst_error(sysinst_t *, const char *); 155 static void sysinst_debug(sysinst_t *, const char *); 156 157 static void sysinst_futil_copy_file(void *, const char *, const char *); 158 static void sysinst_futil_create_dir(void *, const char *); 159 static errno_t sysinst_eject_dev(sysinst_t *, service_id_t); 160 static errno_t sysinst_eject_phys_by_mp(sysinst_t *, const char *); 161 162 static futil_cb_t sysinst_futil_cb = { 163 .copy_file = sysinst_futil_copy_file, 164 .create_dir = sysinst_futil_create_dir 165 }; 166 167 static void sysinst_error_msg_button(ui_msg_dialog_t *, void *, unsigned); 168 static void sysinst_error_msg_close(ui_msg_dialog_t *, void *); 169 170 static ui_msg_dialog_cb_t sysinst_error_msg_cb = { 171 .button = sysinst_error_msg_button, 172 .close = sysinst_error_msg_close 173 }; 174 175 /** Close window. 176 * 177 * @param window Window 178 * @param arg Argument (sysinst_t *) 179 */ 180 static void wnd_close(ui_window_t *window, void *arg) 181 { 182 (void)window; 183 (void)arg; 184 } 185 186 /** Paint background window. 187 * 188 * @param window Window 189 * @param arg Argument (sysinst_t *) 190 */ 191 static errno_t bg_wnd_paint(ui_window_t *window, void *arg) 192 { 193 sysinst_t *sysinst = (sysinst_t *)arg; 194 gfx_rect_t app_rect; 195 gfx_context_t *gc; 196 errno_t rc; 197 198 gc = ui_window_get_gc(window); 199 200 rc = gfx_set_color(gc, sysinst->bg_color); 201 if (rc != EOK) 202 return rc; 203 204 ui_window_get_app_rect(window, &app_rect); 205 206 rc = gfx_fill_rect(gc, &app_rect); 207 if (rc != EOK) 208 return rc; 209 210 rc = gfx_update(gc); 211 if (rc != EOK) 212 return rc; 213 214 return EOK; 215 } 216 217 /** Installation confirm dialog OK button press. 218 * 219 * @param dialog Message dialog 220 * @param arg Argument (sysinst_t *) 221 * @param btn Button number 222 * @param earg Entry argument 223 */ 224 static void sysinst_confirm_button(ui_msg_dialog_t *dialog, void *arg, 225 unsigned btn) 226 { 227 sysinst_t *sysinst = (sysinst_t *) arg; 228 229 ui_msg_dialog_destroy(dialog); 230 231 switch (btn) { 232 case 0: 233 /* OK */ 234 sysinst_start(sysinst); 235 break; 236 default: 237 /* Cancel */ 238 ui_quit(sysinst->ui); 239 break; 240 } 241 } 242 243 /** Installation confirm dialog close request. 244 * 245 * @param dialog Message dialog 246 * @param arg Argument (sysinst_t *) 247 */ 248 static void sysinst_confirm_close(ui_msg_dialog_t *dialog, void *arg) 249 { 250 sysinst_t *sysinst = (sysinst_t *) arg; 251 252 ui_msg_dialog_destroy(dialog); 253 ui_quit(sysinst->ui); 254 } 255 256 /** Restart system dialog OK button press. 257 * 258 * @param dialog Message dialog 259 * @param arg Argument (sysinst_t *) 260 * @param btn Button number 261 * @param earg Entry argument 262 */ 263 static void sysinst_restart_dlg_button(ui_msg_dialog_t *dialog, void *arg, 264 unsigned btn) 265 { 266 sysinst_t *sysinst = (sysinst_t *) arg; 267 268 ui_msg_dialog_destroy(dialog); 269 270 (void)sysinst; 271 272 switch (btn) { 273 case 0: 274 /* OK */ 275 sysinst_action(sysinst, "Ejecting installation media."); 276 (void)sysinst_eject_phys_by_mp(sysinst, CD_MOUNT_POINT); 277 (void)sysinst_restart(sysinst); 278 break; 279 default: 280 /* Cancel */ 281 ui_quit(sysinst->ui); 282 break; 283 } 284 } 285 286 /** Restat system dialog close request. 287 * 288 * @param dialog Message dialog 289 * @param arg Argument (sysinst_t *) 290 */ 291 static void sysinst_restart_dlg_close(ui_msg_dialog_t *dialog, void *arg) 292 { 293 sysinst_t *sysinst = (sysinst_t *) arg; 294 295 ui_msg_dialog_destroy(dialog); 296 ui_quit(sysinst->ui); 297 } 298 299 /** Installation error message dialog button press. 300 * 301 * @param dialog Message dialog 302 * @param arg Argument (sysinst_t *) 303 * @param bnum Button number 304 */ 305 static void sysinst_error_msg_button(ui_msg_dialog_t *dialog, 306 void *arg, unsigned bnum) 307 { 308 sysinst_t *sysinst = (sysinst_t *) arg; 309 310 ui_msg_dialog_destroy(dialog); 311 ui_quit(sysinst->ui); 312 } 313 314 /** Installation error message dialog close request. 315 * 316 * @param dialog Message dialog 317 * @param arg Argument (shutdown_dlg_t *) 318 */ 319 static void sysinst_error_msg_close(ui_msg_dialog_t *dialog, void *arg) 320 { 321 sysinst_t *sysinst = (sysinst_t *) arg; 322 323 ui_msg_dialog_destroy(dialog); 324 ui_quit(sysinst->ui); 325 } 326 327 /** Create error message dialog. 328 * 329 * @param sysinst System installer 330 * @return EOK on success or an error code 331 */ 332 static errno_t sysinst_error_msg_create(sysinst_t *sysinst) 333 { 334 ui_msg_dialog_params_t params; 335 ui_msg_dialog_t *dialog; 336 errno_t rc; 337 338 ui_msg_dialog_params_init(¶ms); 339 params.caption = "Error"; 340 params.text = sysinst->errmsg; 341 params.flags |= umdf_topmost | umdf_center; 342 343 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 344 if (rc != EOK) 345 return rc; 346 347 ui_msg_dialog_set_cb(dialog, &sysinst_error_msg_cb, (void *)sysinst); 348 349 return EOK; 350 } 351 352 /** Called when futil is starting to copy a file. 353 * 354 * @param arg Argument (sysinst_t *) 355 * @param src Source path 356 * @param dest Destination path 357 */ 358 static void sysinst_futil_copy_file(void *arg, const char *src, 359 const char *dest) 360 { 361 sysinst_t *sysinst = (sysinst_t *)arg; 362 char buf[128]; 363 364 (void)src; 365 snprintf(buf, sizeof(buf), "Copying %s.", dest); 366 sysinst_action(sysinst, buf); 367 } 368 369 /** Called when futil is about to create a directory. 370 * 371 * @param arg Argument (sysinst_t *) 372 * @param dest Destination path 373 */ 374 static void sysinst_futil_create_dir(void *arg, const char *dest) 375 { 376 sysinst_t *sysinst = (sysinst_t *)arg; 377 char buf[128]; 378 379 snprintf(buf, sizeof(buf), "Creating %s.", dest); 380 sysinst_action(sysinst, buf); 381 } 382 383 /** System shutdown complete. 384 * 385 * @param arg Argument (shutdown_t *) 386 */ 387 static void sysinst_shutdown_complete(void *arg) 388 { 389 (void)arg; 390 391 fibril_mutex_lock(&shutdown_lock); 392 shutdown_stopped = true; 393 shutdown_failed = false; 394 fibril_condvar_broadcast(&shutdown_cv); 395 fibril_mutex_unlock(&shutdown_lock); 396 } 397 398 /** System shutdown failed. 399 * 400 * @param arg Argument (not used) 401 */ 402 static void sysinst_shutdown_failed(void *arg) 403 { 404 (void)arg; 405 406 fibril_mutex_lock(&shutdown_lock); 407 shutdown_stopped = true; 408 shutdown_failed = true; 409 fibril_condvar_broadcast(&shutdown_cv); 410 fibril_mutex_unlock(&shutdown_lock); 411 } 412 413 /** Check the if the destination device exists. 414 * 415 * @param dev Disk device 416 * 417 * @return EOK on success or an error code 418 */ 419 static errno_t sysinst_check_dev(const char *dev) 420 { 421 service_id_t sid; 422 errno_t rc; 423 424 rc = loc_service_get_id(dev, &sid, 0); 425 if (rc != EOK) 426 return rc; 427 428 (void)sid; 429 return EOK; 430 } 431 432 /** Label and mount the destination device. 433 * 434 * @param sysinst System installer 88 435 * @param dev Disk device to label 89 436 * @param psvc_id Place to store service ID of the created partition … … 91 438 * @return EOK on success or an error code 92 439 */ 93 static errno_t sysinst_label_dev( const char *dev, service_id_t *psvc_id)94 { 95 fdisk_t *fdisk ;96 fdisk_dev_t *fdev ;440 static errno_t sysinst_label_dev(sysinst_t *sysinst, const char *dev) 441 { 442 fdisk_t *fdisk = NULL; 443 fdisk_dev_t *fdev = NULL; 97 444 fdisk_part_t *part; 98 445 fdisk_part_spec_t pspec; 99 446 fdisk_part_info_t pinfo; 447 bool dir_created = false; 448 bool label_created = false; 100 449 capa_spec_t capa; 101 450 service_id_t sid; 102 451 errno_t rc; 103 452 104 printf("sysinst_label_dev(): get service ID '%s'\n", dev); 453 sysinst_debug(sysinst, "sysinst_label_dev(): get service ID"); 454 105 455 rc = loc_service_get_id(dev, &sid, 0); 106 456 if (rc != EOK) 107 return rc;108 109 printf("sysinst_label_dev(): open device\n");457 goto error; 458 459 sysinst_debug(sysinst, "sysinst_label_dev(): open device"); 110 460 111 461 rc = fdisk_create(&fdisk); 112 462 if (rc != EOK) { 113 printf("Error initializing fdisk.\n");114 return rc;463 sysinst_error(sysinst, "Error initializing fdisk."); 464 goto error; 115 465 } 116 466 117 467 rc = fdisk_dev_open(fdisk, sid, &fdev); 118 468 if (rc != EOK) { 119 printf("Error opening device.\n");120 return rc;121 } 122 123 printf("sysinst_label_dev(): create mount directory\n");469 sysinst_error(sysinst, "Error opening device."); 470 goto error; 471 } 472 473 sysinst_debug(sysinst, "sysinst_label_dev(): create mount directory"); 124 474 125 475 rc = vfs_link_path(MOUNT_POINT, KIND_DIRECTORY, NULL); 126 if (rc != EOK) 127 return rc; 128 129 printf("sysinst_label_dev(): create label\n"); 476 if (rc != EOK) { 477 sysinst_error(sysinst, "Error creating mount directory."); 478 goto error; 479 } 480 481 dir_created = true; 482 483 sysinst_debug(sysinst, "sysinst_label_dev(): create label"); 130 484 131 485 rc = fdisk_label_create(fdev, lt_mbr); 132 486 if (rc != EOK) { 133 printf("Error creating label: %s.\n", str_error(rc)); 134 return rc; 135 } 136 137 printf("sysinst_label_dev(): create partition\n"); 487 sysinst_error(sysinst, "Error creating label."); 488 goto error; 489 } 490 491 label_created = true; 492 493 sysinst_debug(sysinst, "sysinst_label_dev(): create partition"); 138 494 139 495 rc = fdisk_part_get_max_avail(fdev, spc_pri, &capa); 140 496 if (rc != EOK) { 141 printf("Error getting available capacity: %s.\n", str_error(rc)); 142 return rc; 497 sysinst_error(sysinst, 498 "Error getting available capacity."); 499 goto error; 143 500 } 144 501 … … 152 509 rc = fdisk_part_create(fdev, &pspec, &part); 153 510 if (rc != EOK) { 154 printf("Error creating partition.\n");155 return rc;511 sysinst_error(sysinst, "Error creating partition."); 512 goto error; 156 513 } 157 514 158 515 rc = fdisk_part_get_info(part, &pinfo); 159 516 if (rc != EOK) { 160 printf("Error getting partition information.\n"); 161 return rc; 162 } 163 164 printf("sysinst_label_dev(): OK\n"); 165 *psvc_id = pinfo.svc_id; 517 sysinst_error(sysinst, "Error getting partition information."); 518 goto error; 519 } 520 521 sysinst_debug(sysinst, "sysinst_label_dev(): OK"); 522 fdisk_dev_close(fdev); 523 fdisk_destroy(fdisk); 524 sysinst->psvc_id = pinfo.svc_id; 525 return EOK; 526 error: 527 if (label_created) 528 fdisk_label_destroy(fdev); 529 if (dir_created) 530 (void)vfs_unlink_path(MOUNT_POINT); 531 if (fdev != NULL) 532 fdisk_dev_close(fdev); 533 if (fdisk != NULL) 534 fdisk_destroy(fdisk); 535 return rc; 536 } 537 538 /** Finish/unmount destination device. 539 * 540 * @param sysinst System installer 541 * 542 * @return EOK on success or an error code 543 */ 544 static errno_t sysinst_finish_dev(sysinst_t *sysinst) 545 { 546 errno_t rc; 547 548 sysinst_debug(sysinst, "sysinst_finish_dev(): eject target volume"); 549 rc = sysinst_eject_dev(sysinst, sysinst->psvc_id); 550 if (rc != EOK) 551 return rc; 552 553 sysinst_debug(sysinst, "sysinst_finish_dev(): " 554 "deleting mount directory"); 555 (void)vfs_unlink_path(MOUNT_POINT); 556 166 557 return EOK; 167 558 } … … 169 560 /** Set up system volume structure. 170 561 * 171 * @return EOK on success or an error code 172 */ 173 static errno_t sysinst_setup_sysvol(void) 562 * @param sysinst System installer 563 * @return EOK on success or an error code 564 */ 565 static errno_t sysinst_setup_sysvol(sysinst_t *sysinst) 174 566 { 175 567 errno_t rc; … … 188 580 rc = vfs_link_path(path, KIND_DIRECTORY, NULL); 189 581 if (rc != EOK) { 190 printf("Error creating directory '%s'.\n", path);582 sysinst_error(sysinst, "Error creating directory."); 191 583 goto error; 192 584 } … … 199 591 free(path); 200 592 path = NULL; 593 594 /* Copy initial configuration files */ 595 rc = futil_rcopy_contents(sysinst->futil, CFG_FILES_SRC, 596 CFG_FILES_DEST); 597 if (rc != EOK) { 598 sysinst_error(sysinst, "Error copying initial configuration " 599 "files."); 600 return rc; 601 } 201 602 202 603 return EOK; … … 211 612 * @return EOK on success or an error code 212 613 */ 213 static errno_t sysinst_copy_boot_files(void) 214 { 215 errno_t rc; 216 217 printf("sysinst_copy_boot_files(): copy bootloader files\n"); 218 rc = futil_rcopy_contents(BOOT_FILES_SRC, MOUNT_POINT); 219 if (rc != EOK) 220 return rc; 221 222 printf("sysinst_copy_boot_files(): OK\n"); 614 static errno_t sysinst_copy_boot_files(sysinst_t *sysinst) 615 { 616 errno_t rc; 617 618 log_msg(LOG_DEFAULT, LVL_NOTE, 619 "sysinst_copy_boot_files(): copy bootloader files"); 620 rc = futil_rcopy_contents(sysinst->futil, BOOT_FILES_SRC, MOUNT_POINT); 621 if (rc != EOK) { 622 sysinst_error(sysinst, "Error copying bootloader " 623 "files."); 624 return rc; 625 } 626 627 sysinst_debug(sysinst, "sysinst_copy_boot_files(): OK"); 223 628 return EOK; 224 629 } … … 226 631 /** Set up configuration in the initial RAM disk. 227 632 * 228 * @return EOK on success or an error code 229 */ 230 static errno_t sysinst_customize_initrd(void) 633 * @param sysinst System installer 634 * @return EOK on success or an error code 635 */ 636 static errno_t sysinst_customize_initrd(sysinst_t *sysinst) 231 637 { 232 638 errno_t rc; … … 240 646 rc = rd_img_open(MOUNT_POINT "/boot/initrd.img", &rdpath, &rd); 241 647 if (rc != EOK) { 242 printf("Error opening initial RAM disk image.\n");243 goto error; 244 } 245 246 rv = asprintf(&path, "%s%s", rdpath, "/cfg/ volsrv.sif");648 sysinst_error(sysinst, "Error opening initial RAM disk image."); 649 goto error; 650 } 651 652 rv = asprintf(&path, "%s%s", rdpath, "/cfg/initvol.sif"); 247 653 if (rv < 0) { 248 654 rc = ENOMEM; … … 250 656 } 251 657 252 printf("Configuring volume server.\n"); 658 sysinst_debug(sysinst, "Configuring volume server."); 659 253 660 rc = vol_volumes_create(path, &volumes); 254 661 if (rc != EOK) { 255 printf("Error creating volume server configuration.\n"); 662 sysinst_error(sysinst, 663 "Error creating volume server configuration."); 256 664 rc = EIO; 257 665 goto error; 258 666 } 259 667 260 printf("Configuring volume server: look up volume\n");668 sysinst_debug(sysinst, "Configuring volume server: look up volume"); 261 669 rc = vol_volume_lookup_ref(volumes, INST_VOL_LABEL, &volume); 262 670 if (rc != EOK) { 263 printf("Error creating volume server configuration.\n"); 671 sysinst_error(sysinst, 672 "Error creating volume server configuration."); 264 673 rc = EIO; 265 674 goto error; 266 675 } 267 676 268 printf("Configuring volume server: set mount point\n");677 sysinst_debug(sysinst, "Configuring volume server: set mount point"); 269 678 rc = vol_volume_set_mountp(volume, INST_VOL_MP); 270 679 if (rc != EOK) { 271 printf("Error creating system partition configuration.\n"); 680 sysinst_error(sysinst, 681 "Error creating system partition configuration."); 272 682 rc = EIO; 273 683 goto error; 274 684 } 275 685 276 printf("Configuring volume server: delete reference\n"); 686 rc = vol_volumes_sync(volumes); 687 if (rc != EOK) { 688 sysinst_error(sysinst, "Error saving volume confiuration."); 689 goto error; 690 } 691 692 log_msg(LOG_DEFAULT, LVL_NOTE, 693 "Configuring volume server: delete reference"); 277 694 vol_volume_del_ref(volume); 278 695 volume = NULL; 279 printf("Configuring volume server: destroy volumes object\n"); 696 log_msg(LOG_DEFAULT, LVL_NOTE, 697 "Configuring volume server: destroy volumes object"); 280 698 vol_volumes_destroy(volumes); 281 699 volumes = NULL; … … 283 701 rc = rd_img_close(rd); 284 702 if (rc != EOK) { 285 printf("Error closing initial RAM disk image.\n");703 sysinst_error(sysinst, "Error closing initial RAM disk image."); 286 704 rc = EIO; 287 705 goto error; … … 326 744 * Install Grub's boot blocks. 327 745 * 746 * @param sysinst System installer 328 747 * @param devp Disk device 329 748 * @return EOK on success or an error code 330 749 */ 331 static errno_t sysinst_copy_boot_blocks( const char *devp)750 static errno_t sysinst_copy_boot_blocks(sysinst_t *sysinst, const char *devp) 332 751 { 333 752 void *boot_img; … … 343 762 errno_t rc; 344 763 345 printf("sysinst_copy_boot_blocks: Read boot block image.\n"); 346 rc = futil_get_file(BOOT_FILES_SRC "/boot/grub/i386-pc/boot.img", 764 log_msg(LOG_DEFAULT, LVL_NOTE, 765 "sysinst_copy_boot_blocks: Read boot block image."); 766 767 rc = futil_get_file(sysinst->futil, 768 BOOT_FILES_SRC "/boot/grub/i386-pc/boot.img", 347 769 &boot_img, &boot_img_size); 348 770 if (rc != EOK || boot_img_size != 512) 349 771 return EIO; 350 772 351 printf("sysinst_copy_boot_blocks: Read GRUB core image.\n"); 352 rc = futil_get_file(BOOT_FILES_SRC "/boot/grub/i386-pc/core.img", 773 log_msg(LOG_DEFAULT, LVL_NOTE, 774 "sysinst_copy_boot_blocks: Read GRUB core image."); 775 776 rc = futil_get_file(sysinst->futil, 777 BOOT_FILES_SRC "/boot/grub/i386-pc/core.img", 353 778 &core_img, &core_img_size); 354 779 if (rc != EOK) 355 780 return EIO; 356 781 357 printf("sysinst_copy_boot_blocks: get service ID.\n"); 782 log_msg(LOG_DEFAULT, LVL_NOTE, 783 "sysinst_copy_boot_blocks: get service ID."); 784 358 785 rc = loc_service_get_id(devp, &sid, 0); 359 786 if (rc != EOK) 360 787 return rc; 361 788 362 printf("sysinst_copy_boot_blocks: block_init.\n"); 363 rc = block_init(sid, 512); 364 if (rc != EOK) 365 return rc; 366 367 printf("sysinst_copy_boot_blocks: get block size\n"); 789 log_msg(LOG_DEFAULT, LVL_NOTE, 790 "sysinst_copy_boot_blocks: block_init."); 791 792 rc = block_init(sid); 793 if (rc != EOK) 794 return rc; 795 796 log_msg(LOG_DEFAULT, LVL_NOTE, 797 "sysinst_copy_boot_blocks: get block size"); 798 368 799 rc = block_get_bsize(sid, &bsize); 369 800 if (rc != EOK) … … 371 802 372 803 if (bsize != 512) { 373 printf("Device block size != 512.\n");804 sysinst_error(sysinst, "Device block size != 512."); 374 805 return EIO; 375 806 } 376 807 377 printf("sysinst_copy_boot_blocks: read boot block\n"); 808 log_msg(LOG_DEFAULT, LVL_NOTE, 809 "sysinst_copy_boot_blocks: read boot block"); 810 378 811 rc = block_read_direct(sid, BOOT_BLOCK_IDX, 1, bbuf); 379 812 if (rc != EOK) … … 390 823 --bl; 391 824 if ((void *)bl < core_img) { 392 printf("No block terminator in core image.\n"); 825 sysinst_error(sysinst, 826 "No block terminator in core image."); 393 827 return EIO; 394 828 } … … 404 838 set_unaligned_u64le(bbuf + grub_boot_machine_kernel_sector, core_start); 405 839 406 printf("sysinst_copy_boot_blocks: write boot block\n"); 840 log_msg(LOG_DEFAULT, LVL_NOTE, 841 "sysinst_copy_boot_blocks: write boot block"); 842 407 843 rc = block_write_direct(sid, BOOT_BLOCK_IDX, 1, bbuf); 408 844 if (rc != EOK) 409 845 return EIO; 410 846 411 printf("sysinst_copy_boot_blocks: write core blocks\n"); 847 log_msg(LOG_DEFAULT, LVL_NOTE, 848 "sysinst_copy_boot_blocks: write core blocks"); 849 412 850 /* XXX Must pad last block with zeros */ 413 851 rc = block_write_direct(sid, core_start, core_blocks, core_img); … … 415 853 return EIO; 416 854 417 printf("sysinst_copy_boot_blocks: OK.\n"); 855 log_msg(LOG_DEFAULT, LVL_NOTE, 856 "sysinst_copy_boot_blocks: OK."); 857 418 858 return EOK; 419 859 } … … 421 861 /** Eject installation volume. 422 862 * 423 * @param psvc_id Partition service ID 424 */ 425 static errno_t sysinst_eject_dev(service_id_t part_id) 863 * @param sysinst System installer 864 * @param part_id Partition service ID 865 * @return EOK on success or an error code 866 */ 867 static errno_t sysinst_eject_dev(sysinst_t *sysinst, service_id_t part_id) 426 868 { 427 869 vol_t *vol = NULL; … … 430 872 rc = vol_create(&vol); 431 873 if (rc != EOK) { 432 printf("Error contacting volume service.\n");874 sysinst_error(sysinst, "Error contacting volume service."); 433 875 goto out; 434 876 } 435 877 436 rc = vol_part_eject(vol, part_id );437 if (rc != EOK) { 438 printf("Error ejecting volume.\n");878 rc = vol_part_eject(vol, part_id, vef_none); 879 if (rc != EOK) { 880 sysinst_error(sysinst, "Error ejecting volume."); 439 881 goto out; 440 882 } … … 446 888 } 447 889 890 /** Physically eject volume by mount point. 891 * 892 * @param sysinst System installer 893 * @param path Mount point 894 * @return EOK on success or an error code 895 */ 896 static errno_t sysinst_eject_phys_by_mp(sysinst_t *sysinst, const char *path) 897 { 898 vol_t *vol = NULL; 899 sysarg_t part_id; 900 errno_t rc; 901 902 log_msg(LOG_DEFAULT, LVL_NOTE, 903 "sysinst_eject_phys_by_mp(%s)", path); 904 905 rc = vol_create(&vol); 906 if (rc != EOK) { 907 sysinst_error(sysinst, "Error contacting volume service."); 908 goto out; 909 } 910 911 log_msg(LOG_DEFAULT, LVL_NOTE, "vol_part_by_mp: mp='%s'\n", 912 path); 913 rc = vol_part_by_mp(vol, path, &part_id); 914 if (rc != EOK) { 915 sysinst_error(sysinst, 916 "Error finding installation media mount point."); 917 goto out; 918 } 919 920 log_msg(LOG_DEFAULT, LVL_NOTE, "eject svc_id %lu", (unsigned long)part_id); 921 rc = vol_part_eject(vol, part_id, vef_physical); 922 if (rc != EOK) { 923 sysinst_error(sysinst, "Error ejecting volume."); 924 goto out; 925 } 926 927 rc = EOK; 928 out: 929 vol_destroy(vol); 930 return rc; 931 } 932 933 /** Restart the system. 934 * 935 * @param sysinst System installer 936 * @return EOK on success or an error code 937 */ 938 static errno_t sysinst_restart(sysinst_t *sysinst) 939 { 940 errno_t rc; 941 system_t *system; 942 943 fibril_mutex_initialize(&shutdown_lock); 944 fibril_condvar_initialize(&shutdown_cv); 945 shutdown_stopped = false; 946 shutdown_failed = false; 947 948 sysinst_action(sysinst, "Restarting the system."); 949 950 rc = system_open(SYSTEM_DEFAULT, &sysinst_system_cb, NULL, &system); 951 if (rc != EOK) { 952 sysinst_error(sysinst, 953 "Failed opening system control service."); 954 return rc; 955 } 956 957 rc = system_restart(system); 958 if (rc != EOK) { 959 system_close(system); 960 sysinst_error(sysinst, "Failed requesting system restart."); 961 return rc; 962 } 963 964 fibril_mutex_lock(&shutdown_lock); 965 sysinst_debug(sysinst, "The system is shutting down..."); 966 967 while (!shutdown_stopped) 968 fibril_condvar_wait(&shutdown_cv, &shutdown_lock); 969 970 if (shutdown_failed) { 971 sysinst_error(sysinst, "Shutdown failed."); 972 system_close(system); 973 return rc; 974 } 975 976 log_msg(LOG_DEFAULT, LVL_NOTE, 977 "Shutdown complete. It is now safe to remove power."); 978 979 /* Sleep forever */ 980 while (true) 981 fibril_condvar_wait(&shutdown_cv, &shutdown_lock); 982 983 fibril_mutex_unlock(&shutdown_lock); 984 985 system_close(system); 986 return 0; 987 988 } 989 448 990 /** Install system to a device. 449 991 * 992 * @parma sysinst System installer 450 993 * @param dev Device to install to. 451 994 * @return EOK on success or an error code 452 995 */ 453 static errno_t sysinst_install(const char *dev) 454 { 455 errno_t rc; 456 service_id_t psvc_id; 457 458 rc = sysinst_label_dev(dev, &psvc_id); 459 if (rc != EOK) 460 return rc; 461 462 printf("FS created and mounted. Creating system directory structure.\n"); 463 rc = sysinst_setup_sysvol(); 464 if (rc != EOK) 465 return rc; 466 467 printf("Directories created. Copying boot files.\n"); 468 rc = sysinst_copy_boot_files(); 469 if (rc != EOK) 470 return rc; 471 472 printf("Boot files done. Configuring the system.\n"); 473 rc = sysinst_customize_initrd(); 474 if (rc != EOK) 475 return rc; 476 477 printf("Boot files done. Installing boot blocks.\n"); 478 rc = sysinst_copy_boot_blocks(dev); 479 if (rc != EOK) 480 return rc; 481 482 printf("Ejecting device.\n"); 483 rc = sysinst_eject_dev(psvc_id); 484 if (rc != EOK) 485 return rc; 486 487 return EOK; 996 static errno_t sysinst_install(sysinst_t *sysinst, const char *dev) 997 { 998 errno_t rc; 999 bool clean_dev = false; 1000 1001 sysinst_action(sysinst, "Creating device label and file system."); 1002 1003 rc = sysinst_label_dev(sysinst, dev); 1004 if (rc != EOK) 1005 goto error; 1006 1007 clean_dev = true; 1008 1009 sysinst_action(sysinst, "Creating system directory structure."); 1010 rc = sysinst_setup_sysvol(sysinst); 1011 if (rc != EOK) 1012 goto error; 1013 1014 sysinst_action(sysinst, "Copying boot files."); 1015 rc = sysinst_copy_boot_files(sysinst); 1016 if (rc != EOK) 1017 goto error; 1018 1019 sysinst_action(sysinst, "Configuring the system."); 1020 rc = sysinst_customize_initrd(sysinst); 1021 if (rc != EOK) 1022 goto error; 1023 1024 sysinst_action(sysinst, "Finishing system volume."); 1025 rc = sysinst_finish_dev(sysinst); 1026 if (rc != EOK) 1027 goto error; 1028 1029 clean_dev = false; 1030 1031 sysinst_action(sysinst, "Installing boot blocks."); 1032 rc = sysinst_copy_boot_blocks(sysinst, dev); 1033 if (rc != EOK) 1034 return rc; 1035 1036 return EOK; 1037 error: 1038 if (clean_dev) 1039 (void)sysinst_finish_dev(sysinst); 1040 return rc; 1041 } 1042 1043 /** Installation fibril. 1044 * 1045 * @param arg Argument (sysinst_t *) 1046 * @return EOK on success or an error code 1047 */ 1048 static errno_t sysinst_install_fibril(void *arg) 1049 { 1050 sysinst_t *sysinst = (sysinst_t *)arg; 1051 unsigned i; 1052 errno_t rc; 1053 1054 (void)sysinst; 1055 1056 i = 0; 1057 while (default_devs[i] != NULL) { 1058 rc = sysinst_check_dev(default_devs[i]); 1059 if (rc == EOK) 1060 break; 1061 ++i; 1062 } 1063 1064 if (default_devs[i] == NULL) { 1065 sysinst_error(sysinst, "Cannot determine installation device."); 1066 rc = ENOENT; 1067 goto error; 1068 } 1069 1070 rc = sysinst_install(sysinst, default_devs[i]); 1071 if (rc != EOK) 1072 goto error; 1073 1074 sysinst_progress_destroy(sysinst->progress); 1075 sysinst->progress = NULL; 1076 1077 rc = sysinst_restart_dlg_create(sysinst); 1078 if (rc != EOK) 1079 goto error; 1080 1081 return EOK; 1082 error: 1083 ui_lock(sysinst->ui); 1084 sysinst_progress_destroy(sysinst->progress); 1085 (void)sysinst_error_msg_create(sysinst); 1086 ui_unlock(sysinst->ui); 1087 return rc; 1088 } 1089 1090 /** Create installation progress window. 1091 * 1092 * @param sysinst System installer 1093 * @param rprogress Place to store pointer to new progress window 1094 * @return EOK on success or an error code 1095 */ 1096 static errno_t sysinst_progress_create(sysinst_t *sysinst, 1097 sysinst_progress_t **rprogress) 1098 { 1099 ui_wnd_params_t params; 1100 ui_window_t *window = NULL; 1101 gfx_rect_t rect; 1102 gfx_rect_t arect; 1103 ui_resource_t *ui_res; 1104 sysinst_progress_t *progress; 1105 ui_fixed_t *fixed = NULL; 1106 errno_t rc; 1107 1108 ui_wnd_params_init(¶ms); 1109 params.caption = "System Installation"; 1110 params.style &= ~ui_wds_titlebar; 1111 params.flags |= ui_wndf_topmost; 1112 params.placement = ui_wnd_place_center; 1113 if (ui_is_textmode(sysinst->ui)) { 1114 params.rect.p0.x = 0; 1115 params.rect.p0.y = 0; 1116 params.rect.p1.x = 64; 1117 params.rect.p1.y = 5; 1118 } else { 1119 params.rect.p0.x = 0; 1120 params.rect.p0.y = 0; 1121 params.rect.p1.x = 500; 1122 params.rect.p1.y = 60; 1123 } 1124 1125 progress = calloc(1, sizeof(sysinst_progress_t)); 1126 if (progress == NULL) { 1127 rc = ENOMEM; 1128 sysinst_error(sysinst, "Out of memory."); 1129 goto error; 1130 } 1131 1132 rc = ui_window_create(sysinst->ui, ¶ms, &window); 1133 if (rc != EOK) { 1134 sysinst_error(sysinst, "Error creating window."); 1135 goto error; 1136 } 1137 1138 ui_window_set_cb(window, &progress_window_cb, (void *)sysinst); 1139 1140 ui_res = ui_window_get_res(window); 1141 1142 rc = ui_fixed_create(&fixed); 1143 if (rc != EOK) { 1144 sysinst_error(sysinst, "Error creating fixed layout."); 1145 goto error; 1146 } 1147 1148 rc = ui_label_create(ui_res, "Installing system. Please wait...", 1149 &progress->label); 1150 if (rc != EOK) { 1151 sysinst_error(sysinst, "Error creating label."); 1152 goto error; 1153 } 1154 1155 ui_window_get_app_rect(window, &arect); 1156 1157 if (ui_is_textmode(sysinst->ui)) { 1158 rect.p0.x = arect.p0.x; 1159 rect.p0.y = arect.p0.y; 1160 rect.p1.x = arect.p1.x; 1161 rect.p1.y = 2; 1162 } else { 1163 rect.p0.x = arect.p0.x; 1164 rect.p0.y = arect.p0.y; 1165 rect.p1.x = arect.p1.x; 1166 rect.p1.y = 30; 1167 } 1168 ui_label_set_rect(progress->label, &rect); 1169 ui_label_set_halign(progress->label, gfx_halign_center); 1170 ui_label_set_valign(progress->label, gfx_valign_center); 1171 1172 rc = ui_fixed_add(fixed, ui_label_ctl(progress->label)); 1173 if (rc != EOK) { 1174 sysinst_error(sysinst, "Error adding control to layout."); 1175 ui_label_destroy(progress->label); 1176 progress->label = NULL; 1177 goto error; 1178 } 1179 1180 rc = ui_label_create(ui_res, "", 1181 &progress->action); 1182 if (rc != EOK) { 1183 sysinst_error(sysinst, "Error creating label."); 1184 goto error; 1185 } 1186 1187 if (ui_is_textmode(sysinst->ui)) { 1188 rect.p0.x = arect.p0.x; 1189 rect.p0.y = 3; 1190 rect.p1.x = arect.p1.x; 1191 rect.p1.y = arect.p1.y; 1192 } else { 1193 rect.p0.x = arect.p0.x; 1194 rect.p0.y = 30; 1195 rect.p1.x = arect.p1.x; 1196 rect.p1.y = arect.p1.y; 1197 } 1198 ui_label_set_rect(progress->action, &rect); 1199 ui_label_set_halign(progress->action, gfx_halign_center); 1200 ui_label_set_valign(progress->action, gfx_valign_center); 1201 1202 rc = ui_fixed_add(fixed, ui_label_ctl(progress->action)); 1203 if (rc != EOK) { 1204 sysinst_error(sysinst, "Error adding control to layout."); 1205 ui_label_destroy(progress->label); 1206 progress->label = NULL; 1207 goto error; 1208 } 1209 1210 ui_window_add(window, ui_fixed_ctl(fixed)); 1211 fixed = NULL; 1212 1213 rc = ui_window_paint(window); 1214 if (rc != EOK) { 1215 sysinst_error(sysinst, "Error painting window."); 1216 goto error; 1217 } 1218 1219 progress->window = window; 1220 progress->fixed = fixed; 1221 *rprogress = progress; 1222 return EOK; 1223 error: 1224 if (progress != NULL && progress->fixed != NULL) 1225 ui_fixed_destroy(progress->fixed); 1226 if (window != NULL) 1227 ui_window_destroy(window); 1228 if (progress != NULL) 1229 free(progress); 1230 return rc; 1231 } 1232 1233 /** Destroy installation progress window. 1234 * 1235 * @param sysinst System installer 1236 * @param rprogress Place to store pointer to new progress window 1237 * @return EOK on success or an error code 1238 */ 1239 static void sysinst_progress_destroy(sysinst_progress_t *progress) 1240 { 1241 if (progress == NULL) 1242 return; 1243 1244 ui_window_destroy(progress->window); 1245 free(progress); 1246 } 1247 1248 /** Set current action message. 1249 * 1250 * @param sysinst System installer 1251 * @param action Action text 1252 */ 1253 static void sysinst_action(sysinst_t *sysinst, const char *action) 1254 { 1255 log_msg(LOG_DEFAULT, LVL_NOTE, "%s", action); 1256 1257 if (sysinst->progress == NULL) 1258 return; 1259 1260 ui_label_set_text(sysinst->progress->action, action); 1261 ui_label_paint(sysinst->progress->action); 1262 } 1263 1264 /** Set current error message. 1265 * 1266 * @param sysinst System installer 1267 * @param errmsg Error message 1268 */ 1269 static void sysinst_error(sysinst_t *sysinst, const char *errmsg) 1270 { 1271 str_cpy(sysinst->errmsg, sizeof(sysinst->errmsg), errmsg); 1272 log_msg(LOG_DEFAULT, LVL_ERROR, errmsg); 1273 } 1274 1275 /** Log a debug message. 1276 * 1277 * @param sysinst System installer 1278 * @param errmsg Error message 1279 */ 1280 static void sysinst_debug(sysinst_t *sysinst, const char *msg) 1281 { 1282 log_msg(LOG_DEFAULT, LVL_ERROR, msg); 1283 } 1284 1285 /** Start system installation. 1286 * 1287 * @param sysinst System installer 1288 * @return EOK on success or an error code 1289 */ 1290 static int sysinst_start(sysinst_t *sysinst) 1291 { 1292 errno_t rc; 1293 fid_t fid; 1294 1295 rc = sysinst_progress_create(sysinst, &sysinst->progress); 1296 if (rc != EOK) 1297 return rc; 1298 1299 fid = fibril_create(sysinst_install_fibril, (void *)sysinst); 1300 if (fid == 0) { 1301 sysinst_error(sysinst, "Out of memory."); 1302 return ENOMEM; 1303 } 1304 1305 fibril_add_ready(fid); 1306 return EOK; 1307 } 1308 1309 /** Create installation confirmation dialog. 1310 * 1311 * @param sysinst System installer 1312 * @return EOK on success or an error code 1313 */ 1314 static errno_t sysinst_confirm_create(sysinst_t *sysinst) 1315 { 1316 ui_msg_dialog_params_t params; 1317 ui_msg_dialog_t *dialog; 1318 errno_t rc; 1319 1320 ui_msg_dialog_params_init(¶ms); 1321 params.caption = "System installation"; 1322 params.text = "This will install HelenOS to your computer. Continue?"; 1323 params.choice = umdc_ok_cancel; 1324 params.flags |= umdf_topmost | umdf_center; 1325 1326 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 1327 if (rc != EOK) 1328 return rc; 1329 1330 ui_msg_dialog_set_cb(dialog, &sysinst_confirm_cb, sysinst); 1331 return EOK; 1332 } 1333 1334 /** Create restart dialog. 1335 * 1336 * @param sysinst System installer 1337 * @return EOK on success or an error code 1338 */ 1339 static errno_t sysinst_restart_dlg_create(sysinst_t *sysinst) 1340 { 1341 ui_msg_dialog_params_t params; 1342 ui_msg_dialog_t *dialog; 1343 errno_t rc; 1344 1345 ui_msg_dialog_params_init(¶ms); 1346 params.caption = "Restart System"; 1347 params.text = "Installation complete. Restart the system?"; 1348 params.choice = umdc_ok_cancel; 1349 params.flags |= umdf_topmost | umdf_center; 1350 1351 rc = ui_msg_dialog_create(sysinst->ui, ¶ms, &dialog); 1352 if (rc != EOK) 1353 return rc; 1354 1355 ui_msg_dialog_set_cb(dialog, &sysinst_restart_dlg_cb, sysinst); 1356 return EOK; 1357 } 1358 1359 /** Run system installer on display. 1360 * 1361 * @param display_spec Display specification 1362 * @return EOK on success or an error code 1363 */ 1364 static errno_t sysinst_run(const char *display_spec) 1365 { 1366 ui_t *ui = NULL; 1367 sysinst_t *sysinst; 1368 ui_wnd_params_t params; 1369 errno_t rc; 1370 1371 sysinst = calloc(1, sizeof(sysinst_t)); 1372 if (sysinst == NULL) 1373 return ENOMEM; 1374 1375 rc = futil_create(&sysinst_futil_cb, (void *)sysinst, &sysinst->futil); 1376 if (rc != EOK) { 1377 printf("Out of memory.\n"); 1378 goto error; 1379 } 1380 1381 rc = ui_create(display_spec, &ui); 1382 if (rc != EOK) { 1383 printf("Error creating UI on display %s.\n", display_spec); 1384 goto error; 1385 } 1386 1387 sysinst->ui = ui; 1388 1389 ui_wnd_params_init(¶ms); 1390 params.caption = "System Installation"; 1391 params.style &= ~ui_wds_decorated; 1392 params.placement = ui_wnd_place_full_screen; 1393 params.flags |= ui_wndf_topmost | ui_wndf_nofocus; 1394 1395 rc = ui_window_create(sysinst->ui, ¶ms, &sysinst->bgwindow); 1396 if (rc != EOK) { 1397 printf("Error creating window.\n"); 1398 goto error; 1399 } 1400 1401 ui_window_set_cb(sysinst->bgwindow, &bg_window_cb, (void *)sysinst); 1402 1403 if (ui_is_textmode(sysinst->ui)) { 1404 rc = gfx_color_new_ega(0x17, &sysinst->bg_color); 1405 if (rc != EOK) { 1406 printf("Error allocating color.\n"); 1407 goto error; 1408 } 1409 } else { 1410 rc = gfx_color_new_rgb_i16(0x8000, 0xc800, 0xffff, &sysinst->bg_color); 1411 if (rc != EOK) { 1412 printf("Error allocating color.\n"); 1413 goto error; 1414 } 1415 } 1416 1417 rc = ui_window_paint(sysinst->bgwindow); 1418 if (rc != EOK) { 1419 printf("Error painting window.\n"); 1420 goto error; 1421 } 1422 1423 (void)sysinst_confirm_create(sysinst); 1424 1425 ui_run(ui); 1426 1427 if (sysinst->bgwindow != NULL) 1428 ui_window_destroy(sysinst->bgwindow); 1429 if (sysinst->system != NULL) 1430 system_close(sysinst->system); 1431 gfx_color_delete(sysinst->bg_color); 1432 ui_destroy(ui); 1433 free(sysinst); 1434 return EOK; 1435 error: 1436 if (sysinst->futil != NULL) 1437 futil_destroy(sysinst->futil); 1438 if (sysinst->system != NULL) 1439 system_close(sysinst->system); 1440 if (sysinst->bg_color != NULL) 1441 gfx_color_delete(sysinst->bg_color); 1442 if (sysinst->bgwindow != NULL) 1443 ui_window_destroy(sysinst->bgwindow); 1444 if (ui != NULL) 1445 ui_destroy(ui); 1446 free(sysinst); 1447 return rc; 1448 } 1449 1450 static void print_syntax(void) 1451 { 1452 printf("Syntax: " NAME " [-d <display-spec>]\n"); 488 1453 } 489 1454 490 1455 int main(int argc, char *argv[]) 491 1456 { 492 const char *dev = DEFAULT_DEV; 493 return sysinst_install(dev); 1457 const char *display_spec = UI_ANY_DEFAULT; 1458 errno_t rc; 1459 int i; 1460 1461 i = 1; 1462 while (i < argc && argv[i][0] == '-') { 1463 if (str_cmp(argv[i], "-d") == 0) { 1464 ++i; 1465 if (i >= argc) { 1466 printf("Argument missing.\n"); 1467 print_syntax(); 1468 return 1; 1469 } 1470 1471 display_spec = argv[i++]; 1472 } else { 1473 printf("Invalid option '%s'.\n", argv[i]); 1474 print_syntax(); 1475 return 1; 1476 } 1477 } 1478 1479 if (i < argc) { 1480 print_syntax(); 1481 return 1; 1482 } 1483 1484 if (log_init(NAME) != EOK) { 1485 printf(NAME ": Failed to initialize logging.\n"); 1486 return 1; 1487 } 1488 1489 rc = sysinst_run(display_spec); 1490 if (rc != EOK) 1491 return 1; 1492 1493 return 0; 494 1494 } 495 1495
Note:
See TracChangeset
for help on using the changeset viewer.