diff --git a/Makefile b/Makefile index cfe341d..28b5d99 100644 --- a/Makefile +++ b/Makefile @@ -258,6 +258,7 @@ ${os_filename}: build/os.32k build/os.iso build/os.fat12 build/os.zip.adjusted \ ${dep_bytes_header_32k_size} \ ${dep_bytes_fat12_start} \ ${dep_bytes_fat12_size} \ + ${dep_bytes_gpt_mirror_start} \ ${dep_bytes_gpt_mirror_end} \ ${dep_sectors_fat12_start} \ ${dep_sectors_fat12_size} \ @@ -287,6 +288,14 @@ ${os_filename}: build/os.32k build/os.iso build/os.fat12 build/os.zip.adjusted \ printf "1\nN\n"; \ printf "01\nY\nN\n"; \ printf "p\no\nw\nY\n") | while read str; do echo "$$str"; printf "\033[1;33m%s\033[m\n" "$$str" >&2; sleep 0.01; done | gdisk $@ +# Inject MS-DOS newlines (CR+LF) and comments (":: ") in the GUID field of unused partition table entries, +# so that the part that is to be skipped by MS-DOS does not form a line longer than the MS-DOS maximum +# line length (8192 excluding CR+LF). $i below is the partition entry number, starting from 1 +# The numbers 55 and 118 are arbitrarily chosen so that the space between two CR+LF is less than 8192. + for i in 55 118; do \ + printf "\r\n:: %02x" $$i | dd bs=1 seek=$$(( 1024 + ( ($$i) - 1) * 128 + 16)) count=7 conv=notrunc of=$@; \ + printf "\r\n:: %02x" $$i | dd bs=1 seek=$$(( ${bytes_gpt_mirror_start} + ( ($$i) - 1) * 128 + 16)) count=7 conv=notrunc of=$@; \ + done # splice in zip at the end set -x; dd skip=${bytes_zip_start} seek=${bytes_zip_start} bs=1 conv=notrunc if=build/os.zip.adjusted of=$@ chmod a+x-w $@ diff --git a/example-os/os.asm b/example-os/os.asm index 744ce5f..4add119 100644 --- a/example-os/os.asm +++ b/example-os/os.asm @@ -3,7 +3,17 @@ db "#!/usr/bin/env sh", 0x0a db ": <<'EOF'", 0x0a -db "GOTO msdos", 0x0a +;;; Starting from here until EOF, all data is effectively ignored by Unix shells +;;; End of line for MS-DOS, so that it correctly processes the comment +db 0x0d, 0x0a + +;;; The GOTO target must not be more than one block away (512 bytes by default +;;; on some systems) apparently, so it is impractical since the target is +;;; so far away in our case. Instead, we use a comment, but if there are some +;;; compatibility issues with the comment syntax, we could likely still use +;;; GOTO and insert intermediate jump points. +;; db "GOTO msdos", 0x0d, 0x0a +db ":: " ;;; The #!… above is interpreted as … jnz short 0x7c78 in x86 assembly. times 0x7c78-0x7c00-($-$$) db 0 @@ -66,24 +76,44 @@ db 0x55, 0xaa ;; 0x1fe End the bootsector with 55 AA, which is the MBR signatur ;;; Leave some space for the GPT header and partition table entries (LBA0 = MBR, LBA1 = header, LBA2..33 = GPT partition tables) times (34*512)-($-$$) db 0 +;;; The MS-DOS maximum line length is 8192 (excluding the \r\n), +;;; but the GPT partition table is a bit more than 16384 bytes long. +;;; We therefore inject in the Makefile intermediate \r\n in some +;;; unused partition entries, after the disk image has been +;;; partitioned using gdisk. + +;;; End of line for MS-DOS, so that it correctly processes the GOTO instruction +db 0x0d, 0x0a +db "GOTO msdos", 0x0d, 0x0a + ;;; After the bootsector, close the sh here-document skipped via : <<'EOF' db 0x0a db "EOF", 0x0a db "echo Hello world by the OS, from sh!", 0x0a -db "while sleep 10; do :; done", 0x0a +db "if test $# -ge 1 && test ", 0x22, "$1", 0x22, " = exit", 0x0a +db "then", 0x0a +db ":", 0x0a +db "else", 0x0a +db "while sleep 10", 0x0a, "do", 0x0a, ":", 0x0a, "done", 0x0a +db "fi", 0x0a db "exit", 0x0a ;;; for good measure: go into an infinite loop if the exit did not happen. db "while :; do sleep 1; done", 0x0a -;;; end of the SH section, everything until this point is skipped by MS-DOS batch due to the GOTO' -db ":msdos", 0x0a -db "@cls", 0x0a -db "@echo Hello world by the OS, from MS-DOS!", 0x0a -db "command.com", 0x0a -db "exit", 0x0a +;;; end of the SH section, everything until this point is skipped by MS-DOS batch due to the GOTO +;;; End of line for MS-DOS, so that it correctly processes the :msdos label +db 0x0d, 0x0a +db ":msdos", 0x0d, 0x0a +db "@cls", 0x0d, 0x0a +db "echo Hello world by the OS, from MS-DOS!", 0x0d, 0x0a +db "@goto %1 :pause", 0x0d, 0x0a +db ":pause", 0x0d, 0x0a +db "@pause", 0x0d, 0x0a +db ":exit", 0x0d, 0x0a +db "@exit 0", 0x0d, 0x0a ;;; for good measure: go into an infinite loop if the exit did not happen. -db ":loop", 0x0a -db "GOTO loop", 0x0a +db ":loop", 0x0d, 0x0a +db "@GOTO loop", 0x0d, 0x0a ;;; Fill up to 32k with 0. This constitutes the reserved first 32k at the beginning of an ISO9660 image. times (32*1024)-($-$$) db 0