swriteboot.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include "system.h"
  8. #include <disklabel.h>
  9. #include <config.h>
  10. #include "library.h"
  11. #define SECT_SIZE 512
  12. #define BOOT_SECTOR 2
  13. int read_configured_partition(int disk_fd, char* buf)
  14. {
  15. u_int64_t bootsize, bootsect, bootpart = 0;
  16. long *p = (long *) buf;
  17. if(lseek(disk_fd,60*8,SEEK_SET)<0) {
  18. perror("lseek on disk");
  19. exit(1);
  20. }
  21. /* Find old configuration */
  22. read(disk_fd, &bootsize, sizeof(bootsize));
  23. read(disk_fd, &bootsect, sizeof(bootsect));
  24. if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0)
  25. return 0; /* probably random garbage in the boot block - not
  26. a fatal error */
  27. read(disk_fd, buf, SECT_SIZE);
  28. while ((char *)p < buf + SECT_SIZE)
  29. if (*p++ == ABOOT_MAGIC)
  30. bootpart = *p;
  31. return bootpart;
  32. }
  33. int main(int argc, char **argv)
  34. {
  35. u_int64_t bootsize,kernelsize=0;
  36. u_int64_t bootsect=BOOT_SECTOR;
  37. u_int64_t magicnum=0;
  38. int disk_fd,file_fd,kernel_fd=0;
  39. struct disklabel dlabel;
  40. struct stat s;
  41. int x;
  42. char buf[2048];
  43. int c;
  44. int err=0, part, bootpart=0;
  45. unsigned force_overlap=0;
  46. int verbose=0;
  47. extern int optind;
  48. extern char *optarg;
  49. char *bootfile=0, *device=0, *kernel=0;
  50. while ((c=getopt(argc,argv,"f:c:v?"))!=EOF)
  51. switch(c)
  52. {
  53. case '?':
  54. err=1;
  55. break;
  56. case 'f':
  57. part = atoi(optarg);
  58. if (part < 1 || part > 8) {
  59. fprintf(stderr, "%s: partition number must be in range 1-8\n",
  60. argv[0]);
  61. exit(1);
  62. }
  63. force_overlap |= 1U << (part - 1);
  64. break;
  65. case 'c':
  66. bootpart = atoi(optarg);
  67. if (bootpart < 1 || bootpart > 8) {
  68. fprintf(stderr, "%s: partition number must be in range 1-8\n",
  69. argv[0]);
  70. exit(1);
  71. }
  72. break;
  73. case 'v':
  74. verbose=1;
  75. break;
  76. default:
  77. err=1;
  78. break;
  79. }
  80. if(optind<argc)
  81. device=argv[optind++];
  82. if(optind<argc)
  83. bootfile=argv[optind++];
  84. if(optind<argc)
  85. kernel=argv[optind++];
  86. if(!bootfile || !device || err)
  87. {
  88. fprintf(stderr, "Usage: %s [-f[1-8]] [-c[1-8]] [-v] disk bootfile [kernel]\n",
  89. argv[0]);
  90. exit(1);
  91. }
  92. disk_fd=open(device,O_RDWR);
  93. file_fd=open(bootfile,O_RDONLY);
  94. if(disk_fd<0) {
  95. perror("open disk device");
  96. exit(1);
  97. }
  98. if(file_fd<0) {
  99. perror("open bootfile");
  100. exit(1);
  101. }
  102. if(kernel)
  103. {
  104. kernel_fd=open(kernel,O_RDONLY);
  105. if (kernel_fd<0)
  106. {
  107. perror("open kernel");
  108. exit(1);
  109. }
  110. else
  111. {
  112. if(fstat(kernel_fd,&s)) {
  113. perror("fstat kernel");
  114. exit(1);
  115. }
  116. kernelsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
  117. }
  118. }
  119. if(read_disklabel(disk_fd,&dlabel)) {
  120. fprintf(stderr,"Couldn't get a valid disk label, exiting\n");
  121. exit(1);
  122. }
  123. if(fstat(file_fd,&s)) {
  124. perror("fstat bootfile");
  125. exit(1);
  126. }
  127. bootsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
  128. if(-1 !=(x=overlaplabel(&dlabel,bootsect,bootsize+bootsect+kernelsize,force_overlap)))
  129. {
  130. fprintf(stderr,
  131. "error: bootcode overlaps with partition #%d. "
  132. "If you really want this, use -f%d\n",
  133. x + 1, x + 1);
  134. exit(1);
  135. }
  136. if(!bootpart) {
  137. bootpart = read_configured_partition(disk_fd, buf);
  138. if (verbose) {
  139. if (bootpart) {
  140. printf("preserving boot partition %d\n", bootpart);
  141. } else {
  142. printf("could not find existing aboot, configuring for second partition\n");
  143. }
  144. }
  145. } else {
  146. if (verbose) {
  147. printf("setting boot partition to %d\n", bootpart);
  148. }
  149. }
  150. if(lseek(disk_fd,60*8,SEEK_SET)<0) {
  151. perror("lseek on disk");
  152. exit(1);
  153. }
  154. write(disk_fd,&bootsize,sizeof(bootsize));
  155. write(disk_fd,&bootsect,sizeof(bootsect));
  156. write(disk_fd,&magicnum,sizeof(magicnum));
  157. if (verbose)
  158. {
  159. fprintf(stderr,"bootsize:%lu sectors\n",bootsize);
  160. fprintf(stderr,"bootsect:%lu\n",bootsect);
  161. }
  162. if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
  163. perror("lseek #3 on disk\n");
  164. exit(1);
  165. }
  166. while((x=read(file_fd,buf,2048))>0) {
  167. write(disk_fd,buf,x);
  168. }
  169. close(file_fd);
  170. if (kernel_fd > 0 && kernelsize>0)
  171. {
  172. unsigned long len = 0;
  173. if (verbose)
  174. fprintf(stderr,"kernel:%lu sectors\n",kernelsize);
  175. #if 0
  176. if(lseek(disk,BOOT_SIZE+BOOT_SECTOR*SECT_SIZE,SEEK_SET)<0) {
  177. perror("lseek #4 on disk\n");
  178. exit(1);
  179. }
  180. #endif
  181. while((x=read(kernel_fd,buf,2048))>0)
  182. {
  183. write(disk_fd,buf,x);
  184. len += x;
  185. }
  186. close(kernel_fd);
  187. if ((len+SECT_SIZE-1)/SECT_SIZE != kernelsize)
  188. fprintf(stderr,"warning: kernel read %lu, should be %lu\n",(len+SECT_SIZE-1)/SECT_SIZE,kernelsize);
  189. }
  190. /* Now write the aboot partition config if we had one */
  191. if (bootpart) {
  192. long *p = (long *) buf;
  193. if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
  194. perror("lseek #5 on disk\n");
  195. exit(1);
  196. }
  197. read(disk_fd, buf, SECT_SIZE);
  198. while ((char *)p < buf + SECT_SIZE) {
  199. if (*p++ == ABOOT_MAGIC) {
  200. *p = bootpart;
  201. }
  202. }
  203. lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET);
  204. write(disk_fd, buf, SECT_SIZE);
  205. }
  206. dosumlabel(disk_fd,&dlabel);
  207. close(disk_fd);
  208. if(verbose)
  209. fprintf(stderr,"done!\n");
  210. return 0;
  211. }