⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 Windows上的精简Linux系统
💻 C
📖 第 1 页 / 共 2 页
字号:
  uint8_t pad[105];} __attribute__((packed));const struct geometry *get_disk_image_geometry(uint32_t where, uint32_t size){  static struct geometry hd_geometry = { 0, 0, 0, 0, 0, 0, 0x80 };  struct ptab_entry ptab[4];	/* Partition table buffer */  struct dosemu_header dosemu;  unsigned int sectors, v;  unsigned int max_c, max_h, max_s;  unsigned int c, h, s, offset;  int i;  int drive_specified;  const char *p;  printf("command line: %s\n", shdr->cmdline);  offset = 0;  if ( CMD_HASDATA(p = getcmditem("offset")) && (v = atou(p)) )    offset = v;  sectors = (size-offset) >> 9;  for ( i = 0 ; i < known_geometries ; i++ ) {    if ( sectors == geometries[i].sectors ) {      hd_geometry = geometries[i];      break;    }  }  hd_geometry.sectors = sectors;  hd_geometry.offset  = offset;  /* Do we have a DOSEMU header? */  memcpy(&dosemu, (char *)where+hd_geometry.offset, sizeof dosemu);  if ( !__builtin_memcmp("DOSEMU", dosemu.magic, 7) ) {    /* Always a hard disk unless overruled by command-line options */    hd_geometry.driveno = 0x80;    hd_geometry.type = 0;    hd_geometry.c = dosemu.c;    hd_geometry.h = dosemu.h;    hd_geometry.s = dosemu.s;    hd_geometry.offset += dosemu.offset;    sectors = (size-hd_geometry.offset) >> 9;  }  if ( CMD_HASDATA(p = getcmditem("c")) && (v = atou(p)) )    hd_geometry.c = v;  if ( CMD_HASDATA(p = getcmditem("h")) && (v = atou(p)) )    hd_geometry.h = v;  if ( CMD_HASDATA(p = getcmditem("s")) && (v = atou(p)) )    hd_geometry.s = v;    if ( getcmditem("floppy") != CMD_NOTFOUND ) {    hd_geometry.driveno = 0;    if ( hd_geometry.type == 0 )      hd_geometry.type = 0x10;	/* ATAPI floppy, e.g. LS-120 */    drive_specified = 1;  } else if ( getcmditem("harddisk") != CMD_NOTFOUND ) {    hd_geometry.driveno = 0x80;    hd_geometry.type = 0;    drive_specified = 1;  }  if ( (hd_geometry.c == 0) || (hd_geometry.h == 0) ||       (hd_geometry.s == 0) ) {    /* Hard disk image, need to examine the partition table for geometry */    memcpy(&ptab, (char *)where+hd_geometry.offset+(512-2-4*16), sizeof ptab);        max_c = max_h = 0;  max_s = 1;    for ( i = 0 ; i < 4 ; i++ ) {      if ( ptab[i].type ) {	c = ptab[i].start_c + (ptab[i].start_s >> 6);	s = (ptab[i].start_s & 0x3f);	h = ptab[i].start_h;		if ( max_c < c ) max_c = c;	if ( max_h < h ) max_h = h;	if ( max_s < s ) max_s = s;		c = ptab[i].end_c + (ptab[i].end_s >> 6);	s = (ptab[i].end_s & 0x3f);	h = ptab[i].end_h;		if ( max_c < c ) max_c = c;	if ( max_h < h ) max_h = h;	if ( max_s < s ) max_s = s;      }    }        max_c++; max_h++;		/* Convert to count (1-based) */        if ( !hd_geometry.h )      hd_geometry.h = max_h;    if ( !hd_geometry.s )      hd_geometry.s = max_s;    if ( !hd_geometry.c )      hd_geometry.c = sectors/(hd_geometry.h*hd_geometry.s);  }  if ( (size-hd_geometry.offset) & 0x1ff ) {    puts("MEMDISK: Image has fractional end sector\n");  }  if ( sectors % (hd_geometry.h*hd_geometry.s) ) {    puts("MEMDISK: Image seems to have fractional end cylinder\n");  }  if ( (hd_geometry.c*hd_geometry.h*hd_geometry.s) > sectors ) {    puts("MEMDISK: Image appears to be truncated\n");  }  return &hd_geometry;}/* * Jump here if all hope is gone... */void __attribute__((noreturn)) die(void){  asm volatile("sti");  for(;;)    asm volatile("hlt");}#define STACK_NEEDED	256	/* Number of bytes of stack *//* * Actual setup routine * Returns the drive number (which is then passed in %dl to the * called routine.) */syscall_t syscall;void *sys_bounce;uint32_t setup(syscall_t cs_syscall, void *cs_bounce){  unsigned int bin_size = (int) &_binary_memdisk_bin_size;  struct memdisk_header *hptr;  struct patch_area *pptr;  uint16_t driverseg;  uint32_t driverptr, driveraddr;  uint16_t dosmem_k;  uint32_t stddosmem;  const struct geometry *geometry;  int total_size, cmdlinelen;  com32sys_t regs;  uint32_t ramdisk_image, ramdisk_size;  /* Set up global variables */  syscall = cs_syscall;  sys_bounce = cs_bounce;  /* Show signs of life */  printf("%s  %s\n", memdisk_version, copyright);  if ( !shdr->ramdisk_image || !shdr->ramdisk_size ) {    puts("MEMDISK: No ramdisk image specified!\n");    die();  }  ramdisk_image = shdr->ramdisk_image;  ramdisk_size  = shdr->ramdisk_size;  e820map_init();		/* Initialize memory data structure */  get_mem();			/* Query BIOS for memory map */  parse_mem();			/* Parse memory map */  printf("Ramdisk at 0x%08x, length 0x%08x\n",	 ramdisk_image, ramdisk_size);  unzip_if_needed(&ramdisk_image, &ramdisk_size);  geometry = get_disk_image_geometry(ramdisk_image, ramdisk_size);  printf("Disk is %s, %u K, C/H/S = %u/%u/%u\n",	 geometry->driveno ? "hard disk" : "floppy",	 geometry->sectors >> 1,	 geometry->c, geometry->h, geometry->s);  /* Reserve the ramdisk memory */  insertrange(ramdisk_image, ramdisk_size, 2);  parse_mem();			/* Recompute variables */  /* Figure out where it needs to go */  hptr = (struct memdisk_header *) &_binary_memdisk_bin_start;  pptr = (struct patch_area *)(_binary_memdisk_bin_start + hptr->patch_offs);  dosmem_k = rdz_16(BIOS_BASEMEM);  pptr->olddosmem = dosmem_k;  stddosmem = dosmem_k << 10;  /* If INT 15 E820 and INT 12 disagree, go with the most conservative */  if ( stddosmem > dos_mem )    stddosmem = dos_mem;  pptr->driveno   = geometry->driveno;  pptr->drivetype = geometry->type;  pptr->cylinders = geometry->c;  pptr->heads     = geometry->h;  pptr->sectors   = geometry->s;  pptr->disksize  = geometry->sectors;  pptr->diskbuf   = ramdisk_image + geometry->offset;  pptr->statusptr = (geometry->driveno & 0x80) ? 0x474 : 0x441;  /* Set up a drive parameter table */  if ( geometry->driveno & 0x80 ) {    /* Hard disk */    pptr->dpt.hd.max_cyl  = geometry->c-1;    pptr->dpt.hd.max_head = geometry->h-1;    pptr->dpt.hd.ctrl     = (geometry->h > 8) ? 0x08: 0;  } else {    /* Floppy - most of these fields are bogus and mimic       a 1.44 MB floppy drive */    pptr->dpt.fd.specify1 = 0xdf;    pptr->dpt.fd.specify2 = 0x02;    pptr->dpt.fd.delay    = 0x25;    pptr->dpt.fd.sectors  = geometry->s;    pptr->dpt.fd.bps      = 0x02;    pptr->dpt.fd.isgap    = 0x12;    pptr->dpt.fd.dlen     = 0xff;    pptr->dpt.fd.fgap     = 0x6c;    pptr->dpt.fd.ffill    = 0xf6;    pptr->dpt.fd.settle   = 0x0f;    pptr->dpt.fd.mstart   = 0x05;    pptr->dpt.fd.old_fd_dpt = rdz_32(BIOS_INT1E);  }  /* The size is given by hptr->total_size plus the size of the E820     map -- 12 bytes per range; we may need as many as 2 additional     ranges (each insertrange() can worst-case turn 1 area into 3)     plus the terminating range, over what nranges currently show. */  cmdlinelen = strlen(shdr->cmdline)+1;  total_size  =  hptr->total_size; 		/* Actual memdisk code */  total_size += (nranges+3)*sizeof(ranges[0]);  /* E820 memory ranges */  total_size += cmdlinelen;	                /* Command line */  total_size += STACK_NEEDED;	                /* Stack */  printf("Total size needed = %u bytes, allocating %uK\n",	 total_size, (total_size+0x3ff) >> 10);  if ( total_size > dos_mem ) {    puts("MEMDISK: Insufficient low memory\n");    die();  }  driveraddr  = stddosmem - total_size;  driveraddr &= ~0x3FF;  printf("Old dos memory at 0x%05x (map says 0x%05x), loading at 0x%05x\n",	 stddosmem, dos_mem, driveraddr);  /* Reserve this range of memory */  wrz_16(BIOS_BASEMEM, driveraddr >> 10);  insertrange(driveraddr, dos_mem-driveraddr, 2);  parse_mem();  pptr->mem1mb     = low_mem  >> 10;  pptr->mem16mb    = high_mem >> 16;  if ( low_mem == (15 << 20) ) {    /* lowmem maxed out */    uint32_t int1588mem = (high_mem >> 10)+(low_mem >> 10);    pptr->memint1588 = (int1588mem > 0xffff) ? 0xffff : int1588mem;  } else {    pptr->memint1588 = low_mem >> 10;  }  printf("1588: 0x%04x  15E801: 0x%04x 0x%04x\n",	 pptr->memint1588, pptr->mem1mb, pptr->mem16mb);  driverseg = driveraddr >> 4;  driverptr = driverseg  << 16;  /* Anything beyond the end is for the stack */  pptr->mystack    = (uint16_t)(stddosmem-driveraddr);  pptr->oldint13 = rdz_32(BIOS_INT13);  pptr->oldint15 = rdz_32(BIOS_INT15);  /* Adjust the E820 table: if there are null ranges (type 0)     at the end, change them to type end of list (-1).     This is necessary for the driver to be able to report end     of list correctly. */  while ( nranges && ranges[nranges-1].type == 0 ) {    ranges[--nranges].type = -1;  }  /* Query drive parameters of this type */  memset(&regs, 0, sizeof regs);  regs.es = 0;  regs.eax.b[1] = 0x08;  regs.edx.b[0] = geometry->driveno;  syscall(0x13, &regs, &regs);    if ( regs.eflags.l & 1 ) {    printf("INT 13 08: Failure, assuming this is the only drive\n");    pptr->drivecnt = 1;  } else {    printf("INT 13 08: Success, count = %u, BPT = %04x:%04x\n",	   regs.edx.b[0], regs.es, regs.edi.w[0]);    pptr->drivecnt = regs.edx.b[0]+1;  }  /* Pointer to the command line */  pptr->cmdline_off = bin_size + (nranges+1)*sizeof(ranges[0]);  pptr->cmdline_seg = driverseg;  /* Copy driver followed by E820 table followed by command line */  {    unsigned char *dpp = (unsigned char *)(driverseg << 4);    dpp = memcpy_endptr(dpp, &_binary_memdisk_bin_start, bin_size);    dpp = memcpy_endptr(dpp, ranges, (nranges+1)*sizeof(ranges[0]));    dpp = memcpy_endptr(dpp, shdr->cmdline, cmdlinelen+1);  }  /* Install the interrupt handlers */  printf("old: int13 = %08x  int15 = %08x\n",	 rdz_32(BIOS_INT13), rdz_32(BIOS_INT15));    wrz_32(BIOS_INT13, driverptr+hptr->int13_offs);  wrz_32(BIOS_INT15, driverptr+hptr->int15_offs);    printf("new: int13 = %08x  int15 = %08x\n",	 rdz_32(BIOS_INT13), rdz_32(BIOS_INT15));  /* Update various BIOS magic data areas (gotta love this shit) */  if ( geometry->driveno & 0x80 ) {    /* Update BIOS hard disk count */    wrz_8(BIOS_HD_COUNT, rdz_8(BIOS_HD_COUNT)+1);  } else {    /* Update BIOS floppy disk count */    uint8_t equip = rdz_8(BIOS_EQUIP);    if ( equip & 1 ) {      if ( (equip & (3 << 6)) != (3 << 6) ) {	equip += (1 << 6);      }    } else {      equip |= 1;      equip &= ~(3 << 6);    }    wrz_8(BIOS_EQUIP, equip);  }  /* Reboot into the new "disk"; this is also a test for the interrupt hooks */  puts("Loading boot sector... ");  memset(&regs, 0, sizeof regs);  // regs.es = 0;  regs.eax.w[0] = 0x0201;	/* Read sector */  regs.ebx.w[0] = 0x7c00;	/* 0000:7C00 */  regs.ecx.w[0] = 1;		/* One sector */  regs.edx.w[0] = geometry->driveno;  syscall(0x13, &regs, &regs);  if ( regs.eflags.l & 1 ) {    puts("MEMDISK: Failed to load new boot sector\n");    die();  }    if ( getcmditem("pause") != CMD_NOTFOUND ) {    puts("press any key to boot... ");    regs.eax.w[0] = 0;    syscall(0x16, &regs, NULL);  }  puts("booting...\n");  /* On return the assembly code will jump to the boot vector */  return geometry->driveno;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -