1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 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 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
|
/*
** bootstrap.c -- Load and launch the Linux kernel
**
** based on bootstrap.c for Atari Linux booter, Copyright 1993 by Arjan Knor
**
** This file is subject to the terms and conditions of the GNU General Public
** License. See the file COPYING in the main directory of this archive
** for more details.
**
** History:
** 15 Apr 1997 Ported to Mac from Linux 2.0.29 source tree. Changed all
** file calls to MacOS ones; other miscellany. (RLP)
** 15 Jul 1997 Further changes: added map_physical, time zone check
** 25 Sep 1997 Fundamentally changing the way that the kernel's memory
** is allocated. Here are some new rules:
** (1) The kernel has to be loaded into a chunk of memory that is
** physically contiguous (we could circumvent this requirement
** later, but for a first cut, this is necessary).
** (1) The kernel's destination must not overlap the video RAM
######### NOT ANY MORE ->
** (2) The kernel's destination CAN overlap the source so long as
** the destination begins before the source, or an alternate
** copy_and_go must be used (one which copies from high to low)
** Alternate if
** (Src_Ptr+size) >= Dest_Ptr AND
** (Src_Ptr+size) < (Dest_Ptr+size)
** (3) The MMU is not dis-engaged until after the kernel is moved
######### <-
** (4) But, of course, the kernel is moved long after interrupts are
** disabled and there is no turning back to the MacOS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
/*#include <unix.h>*/
#include <setjmp.h>
/* linux specific include files */
#include "linux_a.out.h"
#include "linux_elf.h"
#include "asm_page.h"
#include "asm_setup.h"
#include <ShutDown.h>
#include <Gestalt.h> // JDJ
#include <Sound.h>
#include <Traps.h>
#include <Serial.h>
#include <LowMem.h>
#include <Devices.h>
#include <Appletalk.h>
//#include "penguin.h"
#include "bootstrap_prototypes.h"
#include "appkill_prototypes.h"
#include "penguin_prototypes.h"
#include "penguin_utils.h"
#include "asm_prototypes.h"
#include "videocard_prototypes.h"
#include "MMU.h"
#include "colors.h"
#include "machine.h"
#include "accel_allegro.h"
#include "prefs_dialog.h"
#define MB (1024L * 1024L)
#define MIN_RAMSIZE (3L * MB)
#define TEMP_STACKSIZE 256
#define NEW_COPY_AND_GO_SIZE 0x400
#define BI_ALLOC_SIZE (4096L) // Allocate 4K for bootinfo
#define KERNEL_ALIGN (256L * 1024L) // Kernel alignment, on 256K boundary
/* globals */
struct bootinfo bi;
jmp_buf jmpState;
char *new_copy_and_go_ptr, *new_copy_and_go_p_2_l;
unsigned long v_kernel_major, v_kernel_minor;
/* prototypes */
static unsigned long start_mem, rd_size, memreq, kernel_size, kernel_entry;
static char *memptr, *memptr_reloc;
pascal void alternate_shutdown (void);
pascal void shutdown_routine (void);
char * reloc_log_memptr(void);
void * boot_memcpy(void * dst, const void * src, size_t len);
void boot_flushvol(void);
/* External cache handlig protos */
pascal void XEnableExtCache(void) = { 0x7004,0xA198 };
pascal void XDisableExtCache(void) = { 0x7005,0xA198 };
pascal void XFlushExtCache(void) = { 0x7006,0xA198 };
/*
* boot
*
* The routine that makes it happen. Will handle the
* entire kernel boot process, with help from support
* routines.
*/
void boot(void)
{
unsigned long mem_size, ram_size;
unsigned long log_0_phys, aligned_addr, aligned_size;
int rbv_boot;
OSErr err;
struct Kernel_Offsets kernel_areas;
struct Kernel_Image_Info kernel_info;
cprintf ("\n");
kernel_areas.kernel.start = 0;
kernel_areas.kernel.size = 0;
kernel_areas.kernel.entry = 0;
kernel_areas.boot_info = 0;
kernel_areas.ramdisk.start = 0;
kernel_areas.ramdisk.size = 0;
kernel_info.type = KERNEL_ELF;
kernel_info.phdrs_elf= NULL;
memset(&bi, 0, sizeof(bi));
/*
* This is the error-out.
* Using a long_jmp, we can easily bail out.
*/
memptr = NULL;
if (setjmp(jmpState) != 0)
{
/* Dispose allocated memory */
if (kernel_info.phdrs_elf)
DisposePtr ((Ptr) kernel_info.phdrs_elf);
if (memptr)
DisposePtr ((Ptr) memptr);
/* Returning to caller allows the user to change prefs, etc. */
return;
}
/* open the log file */
if (config.do_logfile && ((err = start_logging()) != noErr))
cprintf("\nWARNING: couldn't open log file (error %d), booting anyway\n", err);
/* Setup the memory mappings */
memory_init ();
/* Set the logical address 0 to its physcal address, i.e.
* if log_0_phys != 0 then this is a RBV boot.
*/
log_0_phys = LogicalToPhysical(0);
rbv_boot = (log_0_phys != 0);
if (rbv_boot) {
cprintf ("\nRBV boot, logical 0x00000000 at 0x%0.8lX\n\n", log_0_phys);
}
/* What's the logical to physical table look like here? */
printLog2PhysTable ();
/*
* boot_init_bootinfo is a very important function!
*
* It will initialize the bootinfo structure with a ton
* of useful information: machine, video, cpu, etc.
*/
if (boot_init_bootinfo () == false)
return;
if (config.debug_mach_specs)
boot_print_mach_specs ();
/* Determine where there is RAM on this machine */
findRAM (&bi.num_memory, &bi.memory[0]);
/* Hack for 020/68851. Kernel "head.S" does not handle
* 020 with > 1 memory segment and kernel not in first
* segment. Force kernel into first memory segment on
* these (020) machines.
*/
check020_kernel_pos(bi.num_memory, &bi.memory[0]);
if (config.debug_boot_info)
cprintf ("Command line is '%s'\n", bi.command_line);
/*
* Parse images and calculate sizes
*/
/* Kernel size bit */
kernel_size = parse_kernel_image (&kernel_info);
kernel_areas.kernel.size = kernel_size;
/* Ram Disk bit */
rd_size = parse_ramdisk ();
/* How much RAM req'd for the kernel, boot_info, and ramdisk */
memreq = kernel_size + BI_ALLOC_SIZE;
/* align load address of ramdisk image, read() is sloooow on odd addr. */
memreq = ((memreq + 3) & ~3) + rd_size;
/*
* Determine a physical block which can hold the kernel
* Since the findRAM routine will sort the bi.memory[] blocks
* in ascending order, we can use the first block since it
* will always be the largest possibly available
*/
/* First, align bi.memory[0].addr on KERNEL_ALIGN */
aligned_size = bi.memory[0].addr & (KERNEL_ALIGN - 1);
if ( aligned_size > 0 ) {
aligned_size = KERNEL_ALIGN - aligned_size;
aligned_addr = bi.memory[0].addr + aligned_size;
aligned_size = bi.memory[0].size - aligned_size;
cprintf("\nKernel not aligned\n +Changing addr 0x%0.8lx to 0x%0.8lx\n +Changing size 0x%0.8lx to 0x%0.8lx\n",
bi.memory[0].addr, aligned_addr, bi.memory[0].size, aligned_size);
bi.memory[0].addr = aligned_addr;
bi.memory[0].size = aligned_size;
}
/* Then, verify size */
if ( (bi.memory[0].size < MIN_RAMSIZE) ||
(bi.memory[0].size < memreq) )
ErrorNum ("*** There appears to be no physical memory contiguously\n large enough for a kernel (0x%0.8lX MB).",
MIN_RAMSIZE / MB);
/* Load the kernel one page after start of mem
* start_mem will be a logical address for the kernel, NOT physical!
*/
start_mem = PhysicalToLogical(bi.memory[0].addr) + PAGE_SIZE;
mem_size = bi.memory[0].size - PAGE_SIZE;
if (memreq > mem_size)
ErrorNumNum ("Not enough memory for requirements (needed %d, you have %d)", memreq, mem_size);
memptr = (char *) NewPtrClear (memreq);
if (!memptr)
ErrorNum ("Unable to allocate memory for kernel and ramdisk total (0x%0.8lX)", memreq);
/* Copy the info into internal structures */
kernel_areas.kernel.start = start_mem;
/* tell us where the kernel will go */
if (config.debug_segment_info) {
cprintf("\nThe kernel will be located at physical 0x%08lx\n",
LogicalToPhysical (kernel_areas.kernel.start));
cprintf("Kernel at logical address 0x%lx\n", (unsigned long) memptr);
}
/* Check if ptr contiguous, if not then relocate to another logical block
* Routine fails if relocation not possible
*/
memptr_reloc = reloc_log_memptr();
if (config.debug_segment_info && (memptr_reloc != (char *)0xFFFFFFFF)) {
cprintf(">>>Logical image of kernel/ramdisk split, must relocate\n");
cprintf(">>>Relocated image(s) to:\n logical: 0x%08lX\n physical: 0x%08lX\n size: 0x%08lX\n",
(unsigned long)memptr_reloc, LogicalToPhysical((unsigned long)memptr_reloc), memreq);
if (rd_size)
cprintf(">>>Ramdisk physical src: 0x%08lX\n", LogicalToPhysical((unsigned long)(memptr_reloc + memreq - rd_size)));
}
/* Read the kernel */
parse_read_kernel (&kernel_info, (unsigned long) memptr);
/* Check kernel's bootinfo version */
if (!check_bootinfo_version(memptr))
Error ("Boot Info Version test failed");
if (rd_size) {
/* read the ramdisk image */
parse_read_ramdisk (rd_size, (unsigned long) (memptr + memreq - rd_size));
}
/* The Kernel needs to know where the RAM disk will be, in Physical space */
if (rd_size) {
bi.ramdisk_addr = LogicalToPhysical (start_mem + mem_size - rd_size);
kernel_areas.ramdisk.start = memreq - rd_size;
kernel_areas.ramdisk.size = rd_size;
} else {
bi.ramdisk_addr = 0;
kernel_areas.ramdisk.start = 0;
}
/* copy the boot_info struct to the end of the kernel image */
set_kernel_bootinfo(memptr + kernel_size, v_kernel_major, v_kernel_minor);
kernel_areas.boot_info = kernel_size;
/* Copy and Go has been moved to logical 0 */
new_copy_and_go_ptr = (char *)0;
/* Get new_copy_and_go_ptr physical to logical translation, i.e. where the
* bootstrap code will be located when the MMU is disabled. This is only
* neccessary when logical(0) != physical(0) (a 'rbv boot' where the video
* circuitry claims RAM to drive the display).
* Should it be a rbv boot then we'll have to copy our bootstrap code
* to the video base since this is where we'll have address 0.
* If we have a logical video address equal to the physical address then
* this not a 'real' RBV boot but a boot with no memory in bank A and
* an external video card. This makes it possible to use the video base
* as the boot code placement, alone, since the MMU does not affect the logical<->
* physical mapping.
*/
if (rbv_boot) {
if (bi.bi_mac.videoaddr == bi.bi_mac.videological) {
new_copy_and_go_ptr = (char *)bi.bi_mac.videological;
new_copy_and_go_p_2_l = new_copy_and_go_ptr;
} else
new_copy_and_go_p_2_l = (char *)bi.bi_mac.videological;
// new_copy_and_go_p_2_l = (char *)PhysicalToLogical((unsigned long)new_copy_and_go_ptr);
} else
new_copy_and_go_p_2_l = new_copy_and_go_ptr;
/* record kernel entry point for posterity */
kernel_entry = (kernel_info.type == KERNEL_ELF)
? kernel_info.exec_elf.e_entry
: kernel_info.exec.a_entry;
kernel_entry = LogicalToPhysical (kernel_entry + start_mem - PAGE_SIZE);
/* "For those about to debug/We salute you" -- AC/DC */
if (config.debug_segment_info) {
cprintf ("Kernel entry physical is %#lx\n", kernel_entry);
boot_dump_segment_info ((unsigned long) memptr, &kernel_info, &kernel_areas,
v_kernel_major, v_kernel_minor);
}
if (config.debug_copy_and_go) {
cprintf ("\nBootstrap logical 1: 0x%08lx\n", (unsigned long)new_copy_and_go_ptr);
if (rbv_boot)
cprintf ("Bootstrap logical 2: 0x%08lx\n", (unsigned long)new_copy_and_go_p_2_l);
cprintf ("Bootstrap physical : 0x%08lx\n", LogicalToPhysical((unsigned long)new_copy_and_go_ptr));
};
if (config.debug_boot_info) {
boot_dump_boot_info(memptr + kernel_size, v_kernel_major, v_kernel_minor);
}
cprintf("\nBooting Linux (fasten seat belts, please)...\n");
/* anyone not serious about this, please chicken out now */
if (config.no_boot) {
if (config.do_logfile) stop_logging();
cprintf ("...NOT!\n");
SysBeep(1);
DisposePtr ((Ptr)memptr);
return;
};
/* Appletalk must die. die die die. */
if (config.disable_appletalk) {
cprintf ("Killing Appletalk. Oh, the humanity... ");
MPPClose();
cprintf("Dead.\n");
}
/* Wake up the serial ports */
if (config.modem_port.do_config_port
|| config.printer_port.do_config_port) {
cprintf ("Waking up serial ports, no rest for the wicked...\n");
}
if (config.modem_port.do_config_port) {
short refnum;
short seropts;
OSErr sererr;
sererr = OpenDriver("\p.AOut", &refnum);
if (sererr == noErr) {
cprintf ("Modem port awake ");
switch (config.modem_port.port_speed) {
case kSpeedMenu150: seropts = baud150; break;
case kSpeedMenu300: seropts = baud300; break;
case kSpeedMenu600: seropts = baud600; break;
case kSpeedMenu1200: seropts = baud1200; break;
case kSpeedMenu1800: seropts = baud1800; break;
case kSpeedMenu2400: seropts = baud2400; break;
case kSpeedMenu3600: seropts = baud3600; break;
case kSpeedMenu4800: seropts = baud4800; break;
case kSpeedMenu7200: seropts = baud7200; break;
case kSpeedMenu9600: seropts = baud9600; break;
case kSpeedMenu14400: seropts = baud14400; break;
case kSpeedMenu19200: seropts = baud19200; break;
case kSpeedMenu28800: seropts = baud28800; break;
case kSpeedMenu38400: seropts = baud38400; break;
case kSpeedMenu57600: seropts = baud57600; break;
default: seropts = baud9600;
}
switch (config.modem_port.data_size) {
case kSizeMenu8bit: seropts |= data8; break;
case kSizeMenu7bit: seropts |= data7; break;
case kSizeMenu6bit: seropts |= data6; break;
case kSizeMenu5bit: seropts |= data5; break;
default: seropts |= data8;
}
switch (config.modem_port.parity) {
case kParityMenuNone: seropts |= noParity; break;
case kParityMenuOdd: seropts |= oddParity; break;
case kParityMenuEven: seropts |= evenParity; break;
default: seropts |= noParity;
}
switch (config.modem_port.stop_bits) {
case kStopMenu10Stop: seropts |= stop10; break;
case kStopMenu15Stop: seropts |= stop15; break;
case kStopMenu20Stop: seropts |= stop20; break;
default: seropts |= stop10;
}
sererr = Control(refnum, kSERDConfiguration, &seropts);
if (sererr == noErr) {
cprintf ("and configured!\n");
} else {
cprintf ("and not configured, Oops: %d\n", sererr);
}
} else {
cprintf ("Modem port not awake or configured, Oops: %d\n", sererr);
}
}
if (config.printer_port.do_config_port) {
short refnum;
short seropts;
OSErr sererr;
sererr = OpenDriver("\p.BOut", &refnum);
if (sererr == noErr) {
cprintf ("Printer port awake ");
switch (config.printer_port.port_speed) {
case kSpeedMenu150: seropts = baud150; break;
case kSpeedMenu300: seropts = baud300; break;
case kSpeedMenu600: seropts = baud600; break;
case kSpeedMenu1200: seropts = baud1200; break;
case kSpeedMenu1800: seropts = baud1800; break;
case kSpeedMenu2400: seropts = baud2400; break;
case kSpeedMenu3600: seropts = baud3600; break;
case kSpeedMenu4800: seropts = baud4800; break;
case kSpeedMenu7200: seropts = baud7200; break;
case kSpeedMenu9600: seropts = baud9600; break;
case kSpeedMenu14400: seropts = baud14400; break;
case kSpeedMenu19200: seropts = baud19200; break;
case kSpeedMenu28800: seropts = baud28800; break;
case kSpeedMenu38400: seropts = baud38400; break;
case kSpeedMenu57600: seropts = baud57600; break;
default: seropts = baud9600;
}
switch (config.printer_port.data_size) {
case kSizeMenu8bit: seropts |= data8; break;
case kSizeMenu7bit: seropts |= data7; break;
case kSizeMenu6bit: seropts |= data6; break;
case kSizeMenu5bit: seropts |= data5; break;
default: seropts |= data8;
}
switch (config.printer_port.parity) {
case kParityMenuNone: seropts |= noParity; break;
case kParityMenuOdd: seropts |= oddParity; break;
case kParityMenuEven: seropts |= evenParity; break;
default: seropts |= noParity;
}
switch (config.printer_port.stop_bits) {
case kStopMenu10Stop: seropts |= stop10; break;
case kStopMenu15Stop: seropts |= stop15; break;
case kStopMenu20Stop: seropts |= stop20; break;
default: seropts |= stop10;
}
sererr = Control(refnum, kSERDConfiguration, &seropts);
if (sererr == noErr) {
cprintf ("and configured!\n");
} else {
cprintf ("and not configured, Oops: %d\n", sererr);
}
} else {
cprintf ("Printer port not awake or configured, Oops: %d\n", sererr);
}
}
// Patch Allegro 68030 card drivers, if present. The patch keeps the
// accelerator enabled after the driver is shut down.
AllegroDriverFix();
/* now pull the plug on the OS, and turn off VBL's...
the rest should be in the shutdown routine (we hope) */
#ifndef AS_INIT
KillAllOtherApps ();
#endif
/* Swap black and white colors in hardware clut */
if (config.color_by_penguin)
SwapMainDeviceBW();
/* Slot Interrupts, in videocard.c */
turn_off_interrupts ();
if (config.do_logfile)
stop_logging();
/* Install shutdown task & execute it */
ShutDwnInstall (shutdown_routine, sdOnRestart);
ShutDwnStart ();
}
/*
* shutdown_routine
*
* Callback from _ShutDwnStart.
* Starts the kernel boot process
*/
pascal void shutdown_routine (void)
{
// char *kernel_go;
char *memptr_reloc_src;
unsigned long mmu_type, reloc_size;
char hasSonic = 0;
reloc_size = 0;
/* Flush all volumes. Unmount AppleShare's */
boot_flushvol();
/* Pause shortly to allow user to reinsert removable media that's been ejected */
if (config.delay_boot) {
unsigned long current_time, end_time;
GetDateTime(¤t_time);
end_time = current_time + config.boot_delay_time;
cprintf ("Delaying boot %d seconds... ", config.boot_delay_time);
while (end_time > current_time) GetDateTime(¤t_time);
cprintf ("done.\n");
}
/* enter supervisor mode (in case we aren't there already)
* if the trap or EnterSupervisorMode are unimplemented, there's definitely
* no VM, so we're automatically in supervisor mode already
*/
if (have_trap(_DebugUtil) && (DebuggerGetMax() < 8))
(void) EnterSupervisorMode();
/* Disable external cache, cache card on the IIci, onboard
* cache on the IIvx etc.
* We can safely call these routines on any machine since
* the _HWPriv selector should do nothing (more than return an error)
* on machines not having external caches
*/
if (have_trap(_HWPriv)) {
XFlushExtCache();
XDisableExtCache();
}
hasSonic = MacHasHardware(gestaltHasSonic); /* do this before ints are switched off */
/* turn off interrupts... */
disable_interrupts(); /* set CPU interrupt level to 7 (ignore all but NMI's), in asm.c */
/* disable Singer DMA on 660AV/840AV */
if ((bi.bi_mac.id == 60) || (bi.bi_mac.id == 78)) {
cprintf("Killing Singer DMA... ");
*((unsigned short *) 0x50F31200) = 0;
cprintf("done.\n");
}
/* disable SONIC built-in ethernet */
if (hasSonic) {
cprintf("Killing SONIC ethernet... ");
*(long *)(0x50f0a014) = 0x7fffL;
*(long *)(0x50f0a010) = 0L;
cprintf("done.\n");
}
/* disable and flush caches... */
disable_cache(bi.cputype & CPU_MASK);
/* determine MMU type */
if (bi.cputype & CPU_68040)
mmu_type = 3;
else if (bi.cputype & CPU_68030)
mmu_type = 2;
else /* 020 class */
mmu_type = 1;
/* If we had to relocate the image(s), then update the memptr */
if (memptr_reloc != (char *)0xFFFFFFFF) {
memptr_reloc_src = memptr;
memptr = memptr_reloc;
reloc_size = memreq;
}
/* Move the actual bootstrap code into place
* new_copy_and_go_p_2_l and new_copy_and_go_ptr will
* contain the same address if this is _not_ a RBV boot
*/
boot_memcpy ((Ptr) new_copy_and_go_p_2_l, new_copy_and_go, NEW_COPY_AND_GO_SIZE);
boot_memcpy ((Ptr) new_copy_and_go_ptr, new_copy_and_go, NEW_COPY_AND_GO_SIZE);
/* now call the mover - so long, MacOS */
(*((new_mover_ptr)(new_copy_and_go_ptr))) ((char *) LogicalToPhysical((unsigned long)memptr),
(char *) LogicalToPhysical(start_mem),
(char *) LogicalToPhysical((unsigned long)(memptr + memreq - rd_size)),
(char *) bi.ramdisk_addr, /* physical */
(char *) kernel_entry, /* physical */
mmu_type,
kernel_size + BI_ALLOC_SIZE,
rd_size,
1, /* disable MMU, not used */
memptr_reloc_src, /* relocation src */
memptr_reloc, /* relocation dst */
reloc_size, /* relocation size */
v_kernel_major); /* kernel major version, for bootinfo */
/* NOTREACHED */
}
/*
* reloc_log_memptr
*
* Relocate kernel and ramdisk if neccessary. We'll
* have to do this if the memory segment in which
* they currently resides in is not physically contiguous.
* The reason why we have to do this is: the final
* copy routine in which we'll position the kernel
* and ramdisk at their "resting" positions is done
* after we have disabled the MMU and therefore the
* image(s) could have been physically split.
*/
char *
reloc_log_memptr(void)
{
unsigned long phys_memptr;
unsigned long rom_base;
int reloc_err, i, j;
char *result;
result = (char *)0xFFFFFFFF;
/* We only have to do the rest of the routine if we have more than 1 memory bank */
if (bi.num_memory <= 1)
return result;
rom_base = (unsigned long)LMGetROMBase();
phys_memptr = LogicalToPhysical((unsigned long)memptr);
reloc_err = 2; /* 2 - logical block not found, 1 - could not relocate, 0 - ok */
for(i = 0; i < gMemoryMappings.index; i++) {
/* Which logical block is the kernel+ram image in? */
if ( ((unsigned long)memptr >= gMemoryMappings.log2phys[i].logical) &&
((unsigned long)memptr < (gMemoryMappings.log2phys[i].logical + gMemoryMappings.log2phys[i].length))) {
--reloc_err;
/* Is the image contiguous, i.e. does it fit? */
if (((unsigned long)memptr + memreq) >= (gMemoryMappings.log2phys[i].logical + gMemoryMappings.log2phys[i].length)) {
/* No, we have to relocate to a contiguous logical block that fits */
for(j = 0; j < gMemoryMappings.index; j++) {
/* Logical block usable? Below ROM, mapped and sufficient size. */
if ( (gMemoryMappings.log2phys[j].logical < rom_base) &&
(gMemoryMappings.log2phys[j].physical != 0xFFFFFFFF) &&
(gMemoryMappings.log2phys[j].length >= (memreq + PAGE_SIZE)) ) {
/* Found block */
--reloc_err;
result = (char *)gMemoryMappings.log2phys[j].logical + PAGE_SIZE;
break; /* exit for(... */
}
}
} else
--reloc_err;
break; /* exit for(... */
}
}
switch(reloc_err) {
case 0: /* OK - no err */
break;
case 1: /* No block of sufficient size */
Error("*** RBV - physically split image\nNo block of sufficient size to hold image\nQuit applications, install RAM or re-arrange memory banks\n Aborting boot...");
break;
case 2: /* Did not find original ptr in mapping tables */
Error("*** RBV - physically split image\nLogical address of kernel not found in mapping tables\n Aborting boot\n");
break;
default: /* Did not find original ptr in mapping tables */
Error("*** Unknow error while relocating\n Aborting boot\n");
break;
}
return result;
}
/*
* boot_memcpy
*
* "inline" memcpy, since library routines can result
* in trap calls (and we have disabled the interrupts)
* we'll have to do it by ourself
*/
void * boot_memcpy(register void * dst, register const void * src, size_t len)
{
void *result = dst;
while(len > 0) {
*(((char *)dst)++) = *(((char *)src)++);
--len;
}
return result;
}
/*
* boot_flushvol
*
* Flush all local volumes mounted
* try to unmount AppleShare (external) volumes
*/
void boot_flushvol(void)
{
OSErr err;
short vIndex;
VolumeParam vp;
HIOParam hp;
GetVolParmsInfoBuffer vpi;
err = noErr;
vIndex = 1;
/* Index through all available volumes, flushing them as appropriate */
while(err == noErr) {
vp.ioCompletion = nil;
vp.ioNamePtr = nil;
vp.ioVRefNum = 0x8000;
vp.ioVolIndex = vIndex;
err = PBGetVInfoSync((ParmBlkPtr)&vp);
if (err == noErr) {
/* If not locked by hardware or software */
if ((vp.ioVAtrb & 0x8080) == 0) {
hp.ioCompletion = nil;
hp.ioNamePtr = nil;
hp.ioVRefNum = vp.ioVRefNum;
hp.ioBuffer = (char *)&vpi;
hp.ioReqCount = sizeof(vpi);
err = PBHGetVolParmsSync((HParmBlkPtr)&hp);
if (err == noErr) {
/* If not AppleShare server */
if (vpi.vMServerAdr == 0) {
/* If not external FS */
if ( (vpi.vMAttrib & (1L << bHasExtFSVol) == 0) )
PBFlushVolSync((ParmBlkPtr)&vp);
} else {
/* Unmount AppleShare */
vp.ioCompletion = nil;
PBOffLine((ParmBlkPtr)&vp);
vp.ioCompletion = nil;
PBEject((ParmBlkPtr)&vp);
{
EventRecord xx;
GetNextEvent(everyEvent, &xx);
GetNextEvent(everyEvent, &xx);
GetNextEvent(everyEvent, &xx);
}
}
}
}
}
++vIndex;
}
}
|