Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / fs / iso9660 / iso9660_mount.c
diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_mount.c b/qemu/roms/openbios/fs/iso9660/iso9660_mount.c
new file mode 100644 (file)
index 0000000..a581704
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ * some parts from mkisofs (c) J. Schilling
+ *
+ */
+
+#include "libiso9660.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record *idr, char *buffer)
+{
+       int     j;
+        unsigned char ul, uc;
+
+       buffer[0] = 0;
+       if (idr->name_len[0] == 1 && idr->name[0] == 0)
+               strcpy(buffer, ".");
+       else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+               strcpy(buffer, "..");
+       else {
+               switch (volume->ucs_level) {
+               case 3:
+               case 2:
+               case 1:
+                       /*
+                        * Unicode name.
+                        */
+
+                       for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+                               ul = idr->name[j*2+1];
+
+                               /*
+                                * unicode convertion
+                                * up = unls->unls_uni2cs[uh];
+                                *
+                                * if (up == NULL)
+                                *      uc = '\0';
+                                * else
+                                *      uc = up[ul];
+                                *
+                                * we use only low byte
+                                */
+
+                               uc = ul;
+
+                               buffer[j] = uc ? uc : '_';
+                       }
+                       buffer[idr->name_len[0]/2] = '\0';
+                       break;
+               case 0:
+                       /*
+                        * Normal non-Unicode name.
+                        */
+                       strncpy(buffer, idr->name, idr->name_len[0]);
+                       buffer[idr->name_len[0]] = 0;
+                       break;
+               default:
+                       /*
+                        * Don't know how to do these yet.  Maybe they are the same
+                        * as one of the above.
+                        */
+                       break;
+               }
+       }
+}
+
+iso9660_VOLUME *iso9660_mount(int fd)
+{
+       iso9660_VOLUME* volume;
+       struct iso_primary_descriptor *jpd;
+       struct iso_primary_descriptor ipd;
+       int     block;
+       int ucs_level = 0;
+
+       /* read filesystem descriptor */
+
+       seek_io(fd, 16 * ISOFS_BLOCK_SIZE);
+       read_io(fd, &ipd, sizeof (ipd));
+
+       /*
+        * High sierra:
+        *
+        *      DESC TYPE       == 1 (VD_SFS)   offset 8        len 1
+        *      STR ID          == "CDROM"      offset 9        len 5
+        *      STD_VER         == 1            offset 14       len 1
+        */
+
+       /* High Sierra format ? */
+
+       if ((((char *)&ipd)[8] == 1) &&
+           (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
+           (((char *)&ipd)[14] == 1)) {
+               printk("Incompatible format: High Sierra format\n");
+               return NULL;
+       }
+
+       /*
+        * ISO 9660:
+        *
+        *      DESC TYPE       == 1 (VD_PVD)   offset 0        len 1
+        *      STR ID          == "CD001"      offset 1        len 5
+        *      STD_VER         == 1            offset 6        len 1
+        */
+
+       /* NOT ISO 9660 format ? */
+
+       if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+           (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+           (ipd.version[0] != 1)) {
+               return NULL;
+       }
+
+       /* UCS info */
+
+       block = 16;
+
+       jpd = (struct iso_primary_descriptor *)
+               malloc(sizeof(struct iso_primary_descriptor));
+       if (jpd == NULL)
+               return NULL;
+
+       memcpy(jpd, &ipd, sizeof (ipd));
+       while ((uint8_t)jpd->type[0] != ISO_VD_END) {
+
+               /*
+                * If Joliet UCS escape sequence found, we may be wrong
+                */
+
+               if (jpd->unused3[0] == '%' &&
+                   jpd->unused3[1] == '/' &&
+                   (jpd->unused3[3] == '\0' ||
+                   jpd->unused3[3] == ' ') &&
+                   (jpd->unused3[2] == '@' ||
+                   jpd->unused3[2] == 'C' ||
+                   jpd->unused3[2] == 'E')) {
+
+                       if (jpd->version[0] != 1)
+                               break;
+               }
+
+               block++;
+               seek_io(fd, block * ISOFS_BLOCK_SIZE);
+               read_io(fd, jpd, sizeof (*jpd));
+       }
+
+       ucs_level = 0;
+       if (((unsigned char) jpd->type[0] == ISO_VD_END)) {
+               memcpy(jpd, &ipd, sizeof (ipd));
+       } else {
+               switch (jpd->unused3[2]) {
+               case '@':
+                       ucs_level = 1;
+                       break;
+               case 'C':
+                       ucs_level = 2;
+                       break;
+               case 'E':
+                       ucs_level = 3;
+                       break;
+               }
+
+               if (ucs_level && jpd->unused3[3] == ' ')
+                       printk("Warning: Joliet escape sequence uses illegal space at offset 3\n");
+       }
+
+       volume = (iso9660_VOLUME*)malloc(sizeof(iso9660_VOLUME));
+       if (volume == NULL)
+               return NULL;
+
+       volume->descriptor = jpd;
+       volume->ucs_level = ucs_level;
+       volume->fd = fd;
+
+       return volume;
+}
+
+int iso9660_umount(iso9660_VOLUME* volume)
+{
+       if (volume == NULL)
+               return -1;
+       free(volume->descriptor);
+       free(volume);
+       return 0;
+}
+
+int iso9660_probe(int fd, long long offset)
+{
+       struct iso_primary_descriptor ipd;
+
+       seek_io(fd, 16 * ISOFS_BLOCK_SIZE + offset);
+       read_io(fd, &ipd, sizeof (ipd));
+
+       if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+           (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+           (ipd.version[0] != 1)) {
+               return 0;
+       }
+
+       return -1;
+}
+
+struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume)
+{
+       return (struct iso_directory_record *)volume->descriptor->root_directory_record;
+}